From 9f52d281c9697b69ec44cc592445525b50e50182 Mon Sep 17 00:00:00 2001 From: Belen Pruvost Date: Tue, 2 Nov 2021 11:39:57 +0100 Subject: [PATCH] SONAR-15602 - Quality Gate permission delegation logs --- .../org/sonar/db/audit/AuditPersister.java | 5 ++ .../sonar/db/audit/NoOpAuditPersister.java | 11 +++ .../audit/model/AbstractEditorNewValue.java | 40 ++++++++++ .../db/audit/model/GroupEditorNewValue.java | 78 +++++++++++++++++++ .../db/audit/model/UserEditorNewValue.java | 73 +++++++++++++++++ .../QualityGateGroupPermissionsDao.java | 27 +++++-- .../QualityGateGroupPermissionsMapper.java | 6 +- .../QualityGateUserPermissionsDao.java | 27 +++++-- .../QualityGateUserPermissionsMapper.java | 6 +- .../QualityGateGroupPermissionsDaoTest.java | 77 ++++++++++++++---- .../QualityGateUserPermissionsDaoTest.java | 51 +++++++++++- .../db/qualitygate/QualityGateDbTester.java | 17 ++-- .../server/qualitygate/ws/AddGroupAction.java | 4 +- .../server/qualitygate/ws/AddUserAction.java | 2 +- 14 files changed, 381 insertions(+), 43 deletions(-) create mode 100644 server/sonar-db-dao/src/main/java/org/sonar/db/audit/model/AbstractEditorNewValue.java create mode 100644 server/sonar-db-dao/src/main/java/org/sonar/db/audit/model/GroupEditorNewValue.java create mode 100644 server/sonar-db-dao/src/main/java/org/sonar/db/audit/model/UserEditorNewValue.java diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/audit/AuditPersister.java b/server/sonar-db-dao/src/main/java/org/sonar/db/audit/AuditPersister.java index 66b351a4720..5cb1ef06044 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/audit/AuditPersister.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/audit/AuditPersister.java @@ -24,6 +24,7 @@ import org.sonar.db.DbSession; import org.sonar.db.audit.model.ComponentKeyNewValue; import org.sonar.db.audit.model.ComponentNewValue; import org.sonar.db.audit.model.DevOpsPlatformSettingNewValue; +import org.sonar.db.audit.model.AbstractEditorNewValue; import org.sonar.db.audit.model.GroupPermissionNewValue; import org.sonar.db.audit.model.LicenseNewValue; import org.sonar.db.audit.model.PermissionTemplateNewValue; @@ -96,6 +97,10 @@ public interface AuditPersister { void deleteGroupFromPermissionTemplate(DbSession dbSession, PermissionTemplateNewValue newValue); + void addQualityGateEditor(DbSession dbSession, AbstractEditorNewValue newValue); + + void deleteQualityGateEditor(DbSession dbSession, AbstractEditorNewValue newValue); + void addCharacteristicToPermissionTemplate(DbSession dbSession, PermissionTemplateNewValue newValue); void updateCharacteristicInPermissionTemplate(DbSession dbSession, PermissionTemplateNewValue newValue); diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/audit/NoOpAuditPersister.java b/server/sonar-db-dao/src/main/java/org/sonar/db/audit/NoOpAuditPersister.java index d2de8d4d9e5..52a44b4a6ee 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/audit/NoOpAuditPersister.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/audit/NoOpAuditPersister.java @@ -23,6 +23,7 @@ import org.sonar.db.DbSession; import org.sonar.db.audit.model.ComponentKeyNewValue; import org.sonar.db.audit.model.ComponentNewValue; import org.sonar.db.audit.model.DevOpsPlatformSettingNewValue; +import org.sonar.db.audit.model.AbstractEditorNewValue; import org.sonar.db.audit.model.GroupPermissionNewValue; import org.sonar.db.audit.model.LicenseNewValue; import org.sonar.db.audit.model.PermissionTemplateNewValue; @@ -177,6 +178,16 @@ public class NoOpAuditPersister implements AuditPersister { // no op } + @Override + public void addQualityGateEditor(DbSession dbSession, AbstractEditorNewValue newValue) { + // no op + } + + @Override + public void deleteQualityGateEditor(DbSession dbSession, AbstractEditorNewValue newValue) { + // no op + } + @Override public void addCharacteristicToPermissionTemplate(DbSession dbSession, PermissionTemplateNewValue newValue) { // no op diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/audit/model/AbstractEditorNewValue.java b/server/sonar-db-dao/src/main/java/org/sonar/db/audit/model/AbstractEditorNewValue.java new file mode 100644 index 00000000000..0146375640a --- /dev/null +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/audit/model/AbstractEditorNewValue.java @@ -0,0 +1,40 @@ +/* + * 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.model; + +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; + +public abstract class AbstractEditorNewValue extends NewValue { + @Nullable + protected String qualityGateUuid; + @Nullable + protected String qualityGateName; + + @CheckForNull + public String getQualityGateUuid() { + return this.qualityGateUuid; + } + + @CheckForNull + public String getQualityGateName() { + return this.qualityGateName; + } +} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/audit/model/GroupEditorNewValue.java b/server/sonar-db-dao/src/main/java/org/sonar/db/audit/model/GroupEditorNewValue.java new file mode 100644 index 00000000000..d846220e2f2 --- /dev/null +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/audit/model/GroupEditorNewValue.java @@ -0,0 +1,78 @@ +/* + * 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.model; + +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.sonar.db.qualitygate.QualityGateDto; +import org.sonar.db.qualitygate.QualityGateGroupPermissionsDto; +import org.sonar.db.user.GroupDto; + +public class GroupEditorNewValue extends AbstractEditorNewValue { + @Nullable + private String groupUuid; + @Nullable + private String groupName; + + public GroupEditorNewValue(QualityGateGroupPermissionsDto qualityGateGroupPermissionsDto, String qualityGateName, String groupName) { + this.qualityGateUuid = qualityGateGroupPermissionsDto.getQualityGateUuid(); + this.qualityGateName = qualityGateName; + this.groupUuid = qualityGateGroupPermissionsDto.getGroupUuid(); + this.groupName = groupName; + } + + public GroupEditorNewValue(QualityGateDto qualityGateDto, GroupDto groupDto) { + this.qualityGateUuid = qualityGateDto.getUuid(); + this.qualityGateName = qualityGateDto.getName(); + this.groupUuid = groupDto.getUuid(); + this.groupName = groupDto.getName(); + } + + public GroupEditorNewValue(QualityGateDto qualityGateDto) { + this.qualityGateUuid = qualityGateDto.getUuid(); + this.qualityGateName = qualityGateDto.getName(); + } + + public GroupEditorNewValue(GroupDto groupDto) { + this.groupUuid = groupDto.getUuid(); + this.groupName = groupDto.getName(); + } + + @CheckForNull + public String getGroupUuid() { + return this.groupUuid; + } + + @CheckForNull + public String getGroupName() { + return this.groupName; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("{"); + addField(sb, "\"qualityGateUuid\": ", this.qualityGateUuid, true); + addField(sb, "\"qualityGateName\": ", this.qualityGateName, true); + addField(sb, "\"groupUuid\": ", this.groupUuid, true); + addField(sb, "\"groupName\": ", this.groupName, true); + endString(sb); + return sb.toString(); + } +} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/audit/model/UserEditorNewValue.java b/server/sonar-db-dao/src/main/java/org/sonar/db/audit/model/UserEditorNewValue.java new file mode 100644 index 00000000000..32cca98a725 --- /dev/null +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/audit/model/UserEditorNewValue.java @@ -0,0 +1,73 @@ +/* + * 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.model; + +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.sonar.db.qualitygate.QualityGateDto; +import org.sonar.db.qualitygate.QualityGateUserPermissionsDto; +import org.sonar.db.user.UserDto; + +public class UserEditorNewValue extends AbstractEditorNewValue { + @Nullable + private String userUuid; + @Nullable + private String userLogin; + + public UserEditorNewValue(QualityGateUserPermissionsDto qualityGateUserPermissionsDto, String qualityGateName, String userLogin) { + this.qualityGateUuid = qualityGateUserPermissionsDto.getQualityGateUuid(); + this.qualityGateName = qualityGateName; + this.userUuid = qualityGateUserPermissionsDto.getUserUuid(); + this.userLogin = userLogin; + } + + public UserEditorNewValue(@Nullable QualityGateDto qualityGateDto, @Nullable UserDto userDto) { + if (qualityGateDto != null) { + this.qualityGateUuid = qualityGateDto.getUuid(); + this.qualityGateName = qualityGateDto.getName(); + } + + if (userDto != null) { + this.userUuid = userDto.getUuid(); + this.userLogin = userDto.getLogin(); + } + } + + @CheckForNull + public String getUserUuid() { + return this.userUuid; + } + + @CheckForNull + public String getUserLogin() { + return this.userLogin; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("{"); + addField(sb, "\"qualityGateUuid\": ", this.qualityGateUuid, true); + addField(sb, "\"qualityGateName\": ", this.qualityGateName, true); + addField(sb, "\"userUuid\": ", this.userUuid, true); + addField(sb, "\"userLogin\": ", this.userLogin, true); + endString(sb); + return sb.toString(); + } +} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateGroupPermissionsDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateGroupPermissionsDao.java index 11969f911a2..b3b7b3055f8 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateGroupPermissionsDao.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateGroupPermissionsDao.java @@ -25,6 +25,8 @@ import org.sonar.api.utils.System2; import org.sonar.db.Dao; import org.sonar.db.DbSession; import org.sonar.db.Pagination; +import org.sonar.db.audit.AuditPersister; +import org.sonar.db.audit.model.GroupEditorNewValue; import org.sonar.db.user.GroupDto; import org.sonar.db.user.SearchGroupMembershipDto; import org.sonar.db.user.SearchPermissionQuery; @@ -34,9 +36,11 @@ import static org.sonar.db.DatabaseUtils.executeLargeInputs; public class QualityGateGroupPermissionsDao implements Dao { private final System2 system2; + private final AuditPersister auditPersister; - public QualityGateGroupPermissionsDao(System2 system2) { + public QualityGateGroupPermissionsDao(System2 system2, AuditPersister auditPersister) { this.system2 = system2; + this.auditPersister = auditPersister; } public boolean exists(DbSession dbSession, QualityGateDto qualityGate, GroupDto group) { @@ -53,8 +57,9 @@ public class QualityGateGroupPermissionsDao implements Dao { .isEmpty(); } - public void insert(DbSession dbSession, QualityGateGroupPermissionsDto dto) { + public void insert(DbSession dbSession, QualityGateGroupPermissionsDto dto, String qualityGateName, String groupName) { mapper(dbSession).insert(dto, system2.now()); + auditPersister.addQualityGateEditor(dbSession, new GroupEditorNewValue(dto, qualityGateName, groupName)); } public List selectByQuery(DbSession dbSession, SearchPermissionQuery query, Pagination pagination) { @@ -66,15 +71,27 @@ public class QualityGateGroupPermissionsDao implements Dao { } public void deleteByGroup(DbSession dbSession, GroupDto group) { - mapper(dbSession).deleteByGroup(group.getUuid()); + int deletedRows = mapper(dbSession).deleteByGroup(group.getUuid()); + + if (deletedRows > 0) { + auditPersister.deleteQualityGateEditor(dbSession, new GroupEditorNewValue(group)); + } } public void deleteByQualityGateAndGroup(DbSession dbSession, QualityGateDto qualityGate, GroupDto group) { - mapper(dbSession).delete(qualityGate.getUuid(), group.getUuid()); + int deletedRows = mapper(dbSession).delete(qualityGate.getUuid(), group.getUuid()); + + if (deletedRows > 0) { + auditPersister.deleteQualityGateEditor(dbSession, new GroupEditorNewValue(qualityGate, group)); + } } public void deleteByQualityGate(DbSession dbSession, QualityGateDto qualityGate) { - mapper(dbSession).deleteByQualityGate(qualityGate.getUuid()); + int deletedRows = mapper(dbSession).deleteByQualityGate(qualityGate.getUuid()); + + if (deletedRows > 0) { + auditPersister.deleteQualityGateEditor(dbSession, new GroupEditorNewValue(qualityGate)); + } } private static QualityGateGroupPermissionsMapper mapper(DbSession dbSession) { diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateGroupPermissionsMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateGroupPermissionsMapper.java index 609928a9579..eb07ad41028 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateGroupPermissionsMapper.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateGroupPermissionsMapper.java @@ -37,10 +37,10 @@ public interface QualityGateGroupPermissionsMapper { int countByQuery(@Param("query") SearchPermissionQuery query); - void deleteByGroup(@Param("groupUuid") String groupUuid); + int deleteByGroup(@Param("groupUuid") String groupUuid); - void delete(@Param("qualityGateUuid") String qualityGateUuid, @Param("groupUuid") String groupUuid); + int delete(@Param("qualityGateUuid") String qualityGateUuid, @Param("groupUuid") String groupUuid); - void deleteByQualityGate(@Param("qualityGateUuid") String qualityGateUuid); + int deleteByQualityGate(@Param("qualityGateUuid") String qualityGateUuid); } diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateUserPermissionsDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateUserPermissionsDao.java index 18c9440a847..c778144c2a1 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateUserPermissionsDao.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateUserPermissionsDao.java @@ -25,6 +25,8 @@ import org.sonar.api.utils.System2; import org.sonar.db.Dao; import org.sonar.db.DbSession; import org.sonar.db.Pagination; +import org.sonar.db.audit.AuditPersister; +import org.sonar.db.audit.model.UserEditorNewValue; import org.sonar.db.user.SearchPermissionQuery; import org.sonar.db.user.SearchUserMembershipDto; import org.sonar.db.user.UserDto; @@ -32,9 +34,11 @@ import org.sonar.db.user.UserDto; public class QualityGateUserPermissionsDao implements Dao { private final System2 system2; + private final AuditPersister auditPersister; - public QualityGateUserPermissionsDao(System2 system2) { + public QualityGateUserPermissionsDao(System2 system2, AuditPersister auditPersister) { this.system2 = system2; + this.auditPersister = auditPersister; } public boolean exists(DbSession dbSession, QualityGateDto qualityGate, UserDto user) { @@ -52,8 +56,9 @@ public class QualityGateUserPermissionsDao implements Dao { return mapper(dbSession).selectByQualityGateAndUser(qualityGateUuid, userUuid); } - public void insert(DbSession dbSession, QualityGateUserPermissionsDto dto) { + public void insert(DbSession dbSession, QualityGateUserPermissionsDto dto, String qualityGateName, String userLogin) { mapper(dbSession).insert(dto, system2.now()); + auditPersister.addQualityGateEditor(dbSession, new UserEditorNewValue(dto, qualityGateName, userLogin)); } public List selectByQuery(DbSession dbSession, SearchPermissionQuery query, Pagination pagination) { @@ -65,15 +70,27 @@ public class QualityGateUserPermissionsDao implements Dao { } public void deleteByQualityGateAndUser(DbSession dbSession, QualityGateDto qualityGate, UserDto user) { - mapper(dbSession).delete(qualityGate.getUuid(), user.getUuid()); + int deletedRows = mapper(dbSession).delete(qualityGate.getUuid(), user.getUuid()); + + if (deletedRows > 0) { + auditPersister.deleteQualityGateEditor(dbSession, new UserEditorNewValue(qualityGate, user)); + } } public void deleteByUser(DbSession dbSession, UserDto user) { - mapper(dbSession).deleteByUser(user.getUuid()); + int deletedRows = mapper(dbSession).deleteByUser(user.getUuid()); + + if (deletedRows > 0) { + auditPersister.deleteQualityGateEditor(dbSession, new UserEditorNewValue(user)); + } } public void deleteByQualityGate(DbSession dbSession, QualityGateDto qualityGate) { - mapper(dbSession).deleteByQualityGate(qualityGate.getUuid()); + int deletedRows = mapper(dbSession).deleteByQualityGate(qualityGate.getUuid()); + + if (deletedRows > 0) { + auditPersister.deleteQualityGateEditor(dbSession, new UserEditorNewValue(qualityGate)); + } } private static QualityGateUserPermissionsMapper mapper(DbSession dbSession) { diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateUserPermissionsMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateUserPermissionsMapper.java index 5edf1c3aa13..62abaed1a0b 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateUserPermissionsMapper.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/qualitygate/QualityGateUserPermissionsMapper.java @@ -35,10 +35,10 @@ public interface QualityGateUserPermissionsMapper { int countByQuery(@Param("query") SearchPermissionQuery query); - void delete(@Param("qualityGateUuid") String qualityGateUuid, @Param("userUuid") String userUuid); + int delete(@Param("qualityGateUuid") String qualityGateUuid, @Param("userUuid") String userUuid); - void deleteByUser(@Param("userUuid") String userUuid); + int deleteByUser(@Param("userUuid") String userUuid); - void deleteByQualityGate(@Param("qualityGateUuid") String qualityGateUuid); + int deleteByQualityGate(@Param("qualityGateUuid") String qualityGateUuid); } diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/qualitygate/QualityGateGroupPermissionsDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/qualitygate/QualityGateGroupPermissionsDaoTest.java index 4c8027a7232..d76815dc5a9 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/qualitygate/QualityGateGroupPermissionsDaoTest.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/qualitygate/QualityGateGroupPermissionsDaoTest.java @@ -23,11 +23,14 @@ import java.util.Date; import java.util.List; import org.junit.Rule; import org.junit.Test; +import org.mockito.ArgumentCaptor; import org.sonar.api.utils.System2; import org.sonar.core.util.Uuids; import org.sonar.db.DbSession; import org.sonar.db.DbTester; import org.sonar.db.Pagination; +import org.sonar.db.audit.AuditPersister; +import org.sonar.db.audit.model.GroupEditorNewValue; import org.sonar.db.user.GroupDto; import org.sonar.db.user.GroupTesting; import org.sonar.db.user.SearchGroupMembershipDto; @@ -35,15 +38,20 @@ import org.sonar.db.user.SearchGroupMembershipDto; import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.tuple; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import static org.sonar.db.qualitygate.SearchQualityGatePermissionQuery.builder; import static org.sonar.db.user.SearchPermissionQuery.ANY; import static org.sonar.db.user.SearchPermissionQuery.IN; import static org.sonar.db.user.SearchPermissionQuery.OUT; public class QualityGateGroupPermissionsDaoTest { + private final AuditPersister auditPersister = mock(AuditPersister.class); + private final ArgumentCaptor newValueCaptor = ArgumentCaptor.forClass(GroupEditorNewValue.class); @Rule - public DbTester dbTester = DbTester.create(System2.INSTANCE); + public DbTester dbTester = DbTester.create(System2.INSTANCE, auditPersister); private DbSession dbSession = dbTester.getSession(); private QualityGateGroupPermissionsDao underTest = dbTester.getDbClient().qualityGateGroupPermissionsDao(); @@ -52,7 +60,17 @@ public class QualityGateGroupPermissionsDaoTest { public void itInsertsAndExistsReturnsTrue() { GroupDto group = GroupTesting.newGroupDto(); QualityGateDto qualityGateDto = insertQualityGate(); - QualityGateGroupPermissionsDto qualityGateGroupPermission = insertQualityGateGroupPermission(qualityGateDto.getUuid(), group.getUuid()); + QualityGateGroupPermissionsDto qualityGateGroupPermission = insertQualityGateGroupPermission(qualityGateDto.getUuid(), + qualityGateDto.getName(), group.getUuid(), group.getName()); + + verify(auditPersister).addQualityGateEditor(eq(dbSession), newValueCaptor.capture()); + + GroupEditorNewValue newValue = newValueCaptor.getValue(); + assertThat(newValue) + .extracting(GroupEditorNewValue::getQualityGateName, GroupEditorNewValue::getQualityGateUuid, + GroupEditorNewValue::getGroupName, GroupEditorNewValue::getGroupUuid) + .containsExactly(qualityGateDto.getName(), qualityGateDto.getUuid(), group.getName(), group.getUuid()); + assertThat(newValue.toString()).contains("\"qualityGateName\"").contains("\"groupName\""); assertThat(qualityGateGroupPermission.getUuid()).isNotNull(); assertThat(underTest.exists(dbSession, qualityGateDto, group)).isTrue(); @@ -64,7 +82,8 @@ public class QualityGateGroupPermissionsDaoTest { GroupDto group1 = GroupTesting.newGroupDto(); GroupDto group2 = GroupTesting.newGroupDto(); QualityGateDto qualityGateDto = insertQualityGate(); - QualityGateGroupPermissionsDto qualityGateGroupPermission = insertQualityGateGroupPermission(qualityGateDto.getUuid(), group1.getUuid()); + QualityGateGroupPermissionsDto qualityGateGroupPermission = insertQualityGateGroupPermission(qualityGateDto.getUuid(), qualityGateDto.getName(), + group1.getUuid(), group1.getName()); assertThat(qualityGateGroupPermission.getUuid()).isNotNull(); assertThat(underTest.exists(dbSession, qualityGateDto, List.of(group1, group2))).isTrue(); @@ -84,8 +103,8 @@ public class QualityGateGroupPermissionsDaoTest { GroupDto group2 = dbTester.users().insertGroup(); GroupDto group3 = dbTester.users().insertGroup(); - insertQualityGateGroupPermission(qualityGateDto.getUuid(), group1.getUuid()); - insertQualityGateGroupPermission(qualityGateDto.getUuid(), group2.getUuid()); + insertQualityGateGroupPermission(qualityGateDto.getUuid(), qualityGateDto.getName(), group1.getUuid(), group1.getName()); + insertQualityGateGroupPermission(qualityGateDto.getUuid(), qualityGateDto.getName(), group2.getUuid(), group2.getName()); assertThat(underTest.exists(dbSession, qualityGateDto, List.of(group1, group2))).isTrue(); @@ -112,8 +131,8 @@ public class QualityGateGroupPermissionsDaoTest { GroupDto group2 = dbTester.users().insertGroup(); GroupDto group3 = dbTester.users().insertGroup(); - insertQualityGateGroupPermission(qualityGateDto.getUuid(), group1.getUuid()); - insertQualityGateGroupPermission(qualityGateDto.getUuid(), group2.getUuid()); + insertQualityGateGroupPermission(qualityGateDto.getUuid(), qualityGateDto.getName(), group1.getUuid(), group1.getName()); + insertQualityGateGroupPermission(qualityGateDto.getUuid(), qualityGateDto.getName(), group2.getUuid(), group2.getName()); assertThat(underTest.selectByQuery(dbSession, builder() .setQualityGate(qualityGateDto) @@ -146,9 +165,9 @@ public class QualityGateGroupPermissionsDaoTest { GroupDto group2 = dbTester.users().insertGroup("sonar-users-qprofile"); GroupDto group3 = dbTester.users().insertGroup("sonar-admin"); - insertQualityGateGroupPermission(qualityGateDto.getUuid(), group1.getUuid()); - insertQualityGateGroupPermission(qualityGateDto.getUuid(), group2.getUuid()); - insertQualityGateGroupPermission(qualityGateDto.getUuid(), group3.getUuid()); + insertQualityGateGroupPermission(qualityGateDto.getUuid(), qualityGateDto.getName(), group1.getUuid(), group1.getName()); + insertQualityGateGroupPermission(qualityGateDto.getUuid(), qualityGateDto.getName(), group2.getUuid(), group2.getName()); + insertQualityGateGroupPermission(qualityGateDto.getUuid(), qualityGateDto.getName(), group3.getUuid(), group3.getName()); assertThat(underTest.selectByQuery(dbSession, builder() .setQualityGate(qualityGateDto) @@ -174,8 +193,8 @@ public class QualityGateGroupPermissionsDaoTest { GroupDto group2 = dbTester.users().insertGroup("group2"); GroupDto group3 = dbTester.users().insertGroup("group3"); - insertQualityGateGroupPermission(qualityGateDto.getUuid(), group1.getUuid()); - insertQualityGateGroupPermission(qualityGateDto.getUuid(), group2.getUuid()); + insertQualityGateGroupPermission(qualityGateDto.getUuid(), qualityGateDto.getName(), group1.getUuid(), group1.getName()); + insertQualityGateGroupPermission(qualityGateDto.getUuid(), qualityGateDto.getName(), group2.getUuid(), group2.getName()); assertThat(underTest.selectByQuery(dbSession, builder() .setQualityGate(qualityGateDto) @@ -216,6 +235,15 @@ public class QualityGateGroupPermissionsDaoTest { underTest.deleteByGroup(dbSession, group1); + verify(auditPersister).deleteQualityGateEditor(eq(dbSession), newValueCaptor.capture()); + + GroupEditorNewValue newValue = newValueCaptor.getValue(); + assertThat(newValue) + .extracting(GroupEditorNewValue::getQualityGateName, GroupEditorNewValue::getQualityGateUuid, + GroupEditorNewValue::getGroupName, GroupEditorNewValue::getGroupUuid) + .containsExactly(null, null, group1.getName(), group1.getUuid()); + assertThat(newValue.toString()).doesNotContain("\"qualityGateName\"").contains("\"groupName\""); + assertThat(underTest.exists(dbSession, qualityGateDto1, group1)).isFalse(); assertThat(underTest.exists(dbSession, qualityGateDto2, group2)).isTrue(); assertThat(underTest.exists(dbSession, qualityGateDto3, group1)).isFalse(); @@ -225,12 +253,21 @@ public class QualityGateGroupPermissionsDaoTest { public void deleteByQProfileAndGroup() { QualityGateDto qualityGateDto = insertQualityGate(); GroupDto group = dbTester.users().insertGroup(); - insertQualityGateGroupPermission(qualityGateDto.getUuid(), group.getUuid()); + insertQualityGateGroupPermission(qualityGateDto.getUuid(), qualityGateDto.getName(), group.getUuid(), group.getName()); assertThat(underTest.exists(dbSession, qualityGateDto, group)).isTrue(); underTest.deleteByQualityGateAndGroup(dbSession, qualityGateDto, group); + verify(auditPersister).deleteQualityGateEditor(eq(dbSession), newValueCaptor.capture()); + + GroupEditorNewValue newValue = newValueCaptor.getValue(); + assertThat(newValue) + .extracting(GroupEditorNewValue::getQualityGateName, GroupEditorNewValue::getQualityGateUuid, + GroupEditorNewValue::getGroupName, GroupEditorNewValue::getGroupUuid) + .containsExactly(qualityGateDto.getName(), qualityGateDto.getUuid(), group.getName(), group.getUuid()); + assertThat(newValue.toString()).contains("\"qualityGateName\"").contains("\"groupName\""); + assertThat(underTest.exists(dbSession, qualityGateDto, group)).isFalse(); } @@ -247,6 +284,15 @@ public class QualityGateGroupPermissionsDaoTest { underTest.deleteByQualityGate(dbSession, qualityGateDto1); + verify(auditPersister).deleteQualityGateEditor(eq(dbSession), newValueCaptor.capture()); + + GroupEditorNewValue newValue = newValueCaptor.getValue(); + assertThat(newValue) + .extracting(GroupEditorNewValue::getQualityGateName, GroupEditorNewValue::getQualityGateUuid, + GroupEditorNewValue::getGroupName, GroupEditorNewValue::getGroupUuid) + .containsExactly(qualityGateDto1.getName(), qualityGateDto1.getUuid(), null, null); + assertThat(newValue.toString()).contains("\"qualityGateName\"").doesNotContain("\"groupName\""); + assertThat(underTest.exists(dbSession, qualityGateDto1, group1)).isFalse(); assertThat(underTest.exists(dbSession, qualityGateDto2, group2)).isTrue(); assertThat(underTest.exists(dbSession, qualityGateDto3, group1)).isTrue(); @@ -261,13 +307,14 @@ public class QualityGateGroupPermissionsDaoTest { return qg; } - private QualityGateGroupPermissionsDto insertQualityGateGroupPermission(String qualityGateUuid, String groupUuid) { + private QualityGateGroupPermissionsDto insertQualityGateGroupPermission(String qualityGateUuid, String qualityGateName, + String groupUuid, String groupName) { QualityGateGroupPermissionsDto qgg = new QualityGateGroupPermissionsDto() .setUuid(Uuids.create()) .setQualityGateUuid(qualityGateUuid) .setGroupUuid(groupUuid) .setCreatedAt(new Date()); - underTest.insert(dbTester.getSession(), qgg); + underTest.insert(dbTester.getSession(), qgg, qualityGateName, groupName); dbTester.commit(); return qgg; } diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/qualitygate/QualityGateUserPermissionsDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/qualitygate/QualityGateUserPermissionsDaoTest.java index 0c956d9bdca..8cf82da9ef1 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/qualitygate/QualityGateUserPermissionsDaoTest.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/qualitygate/QualityGateUserPermissionsDaoTest.java @@ -21,24 +21,33 @@ package org.sonar.db.qualitygate; import org.junit.Rule; import org.junit.Test; +import org.mockito.ArgumentCaptor; import org.sonar.api.utils.System2; import org.sonar.db.DbSession; import org.sonar.db.DbTester; import org.sonar.db.Pagination; +import org.sonar.db.audit.AuditPersister; +import org.sonar.db.audit.model.UserEditorNewValue; import org.sonar.db.user.SearchUserMembershipDto; import org.sonar.db.user.UserDbTester; import org.sonar.db.user.UserDto; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.tuple; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import static org.sonar.db.qualitygate.SearchQualityGatePermissionQuery.builder; import static org.sonar.db.user.SearchPermissionQuery.ANY; import static org.sonar.db.user.SearchPermissionQuery.IN; import static org.sonar.db.user.SearchPermissionQuery.OUT; public class QualityGateUserPermissionsDaoTest { + private final AuditPersister auditPersister = mock(AuditPersister.class); + private final ArgumentCaptor newValueCaptor = ArgumentCaptor.forClass(UserEditorNewValue.class); + @Rule - public final DbTester db = DbTester.create(System2.INSTANCE); + public final DbTester db = DbTester.create(System2.INSTANCE, auditPersister); private final DbSession dbSession = db.getSession(); private final UserDbTester userDbTester = new UserDbTester(db); @@ -50,9 +59,18 @@ public class QualityGateUserPermissionsDaoTest { UserDto user = userDbTester.insertUser(); QualityGateDto qualityGate = qualityGateDbTester.insertQualityGate(); QualityGateUserPermissionsDto qualityGateUserPermissions = new QualityGateUserPermissionsDto("uuid", user.getUuid(), qualityGate.getUuid()); - underTest.insert(dbSession, qualityGateUserPermissions); + underTest.insert(dbSession, qualityGateUserPermissions, qualityGate.getName(), user.getLogin()); dbSession.commit(); + verify(auditPersister).addQualityGateEditor(eq(db.getSession()), newValueCaptor.capture()); + + UserEditorNewValue newValue = newValueCaptor.getValue(); + assertThat(newValue) + .extracting(UserEditorNewValue::getQualityGateName, UserEditorNewValue::getQualityGateUuid, + UserEditorNewValue::getUserLogin, UserEditorNewValue::getUserUuid) + .containsExactly(qualityGate.getName(), qualityGate.getUuid(), user.getLogin(), user.getUuid()); + assertThat(newValue.toString()).contains("\"qualityGateName\"").contains("\"userLogin\""); + QualityGateUserPermissionsDto fromDB = underTest.selectByQualityGateAndUser(dbSession, qualityGate.getUuid(), user.getUuid()); assertThat(fromDB.getQualityGateUuid()).isEqualTo(qualityGate.getUuid()); assertThat(fromDB.getUserUuid()).isEqualTo(user.getUuid()); @@ -65,7 +83,7 @@ public class QualityGateUserPermissionsDaoTest { UserDto user2 = userDbTester.insertUser(); QualityGateDto qualityGate = qualityGateDbTester.insertQualityGate(); QualityGateUserPermissionsDto qualityGateUserPermissions = new QualityGateUserPermissionsDto("uuid", user1.getUuid(), qualityGate.getUuid()); - underTest.insert(dbSession, qualityGateUserPermissions); + underTest.insert(dbSession, qualityGateUserPermissions, qualityGate.getName(), user1.getLogin()); dbSession.commit(); assertThat(underTest.exists(dbSession, qualityGate.getUuid(), user1.getUuid())).isTrue(); @@ -217,6 +235,15 @@ public class QualityGateUserPermissionsDaoTest { underTest.deleteByQualityGateAndUser(dbSession, qualityGate, user); + verify(auditPersister).deleteQualityGateEditor(eq(db.getSession()), newValueCaptor.capture()); + + UserEditorNewValue newValue = newValueCaptor.getValue(); + assertThat(newValue) + .extracting(UserEditorNewValue::getQualityGateName, UserEditorNewValue::getQualityGateUuid, + UserEditorNewValue::getUserLogin, UserEditorNewValue::getUserUuid) + .containsExactly(qualityGate.getName(), qualityGate.getUuid(), user.getLogin(), user.getUuid()); + assertThat(newValue.toString()).contains("\"qualityGateName\"").contains("\"userLogin\""); + assertThat(underTest.exists(dbSession, qualityGate, user)).isFalse(); } @@ -234,6 +261,15 @@ public class QualityGateUserPermissionsDaoTest { underTest.deleteByUser(dbSession, user1); + verify(auditPersister).deleteQualityGateEditor(eq(db.getSession()), newValueCaptor.capture()); + + UserEditorNewValue newValue = newValueCaptor.getValue(); + assertThat(newValue) + .extracting(UserEditorNewValue::getQualityGateName, UserEditorNewValue::getQualityGateUuid, + UserEditorNewValue::getUserLogin, UserEditorNewValue::getUserUuid) + .containsExactly(null, null, user1.getLogin(), user1.getUuid()); + assertThat(newValue.toString()).doesNotContain("\"qualityGateName\"").contains("\"userLogin\""); + assertThat(underTest.exists(dbSession, qualityGateDto1, user1)).isFalse(); assertThat(underTest.exists(dbSession, qualityGateDto2, user2)).isTrue(); assertThat(underTest.exists(dbSession, qualityGateDto3, user1)).isFalse(); @@ -254,6 +290,15 @@ public class QualityGateUserPermissionsDaoTest { underTest.deleteByQualityGate(dbSession, qualityGateDto1); + verify(auditPersister).deleteQualityGateEditor(eq(db.getSession()), newValueCaptor.capture()); + + UserEditorNewValue newValue = newValueCaptor.getValue(); + assertThat(newValue) + .extracting(UserEditorNewValue::getQualityGateName, UserEditorNewValue::getQualityGateUuid, + UserEditorNewValue::getUserLogin, UserEditorNewValue::getUserUuid) + .containsExactly(qualityGateDto1.getName(), qualityGateDto1.getUuid(), null, null); + assertThat(newValue.toString()).contains("\"qualityGateName\"").doesNotContain("\"userLogin\""); + assertThat(underTest.exists(dbSession, qualityGateDto1, user1)).isFalse(); assertThat(underTest.exists(dbSession, qualityGateDto2, user2)).isTrue(); assertThat(underTest.exists(dbSession, qualityGateDto3, user3)).isTrue(); diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/qualitygate/QualityGateDbTester.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/qualitygate/QualityGateDbTester.java index 1243594bf5f..de312d84cb1 100644 --- a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/qualitygate/QualityGateDbTester.java +++ b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/qualitygate/QualityGateDbTester.java @@ -107,19 +107,22 @@ public class QualityGateDbTester { public void addGroupPermission(QualityGateDto qualityGateDto, GroupDto group) { dbClient.qualityGateGroupPermissionsDao().insert(dbSession, new QualityGateGroupPermissionsDto() - .setUuid(Uuids.createFast()) - .setGroupUuid(group.getUuid()) - .setQualityGateUuid(qualityGateDto.getUuid()) + .setUuid(Uuids.createFast()) + .setGroupUuid(group.getUuid()) + .setQualityGateUuid(qualityGateDto.getUuid()), + qualityGateDto.getName(), + group.getName() ); dbSession.commit(); } public void addUserPermission(QualityGateDto qualityGateDto, UserDto user) { dbClient.qualityGateUserPermissionDao().insert(dbSession, new QualityGateUserPermissionsDto() - .setUuid(Uuids.createFast()) - .setUserUuid(user.getUuid()) - .setQualityGateUuid(qualityGateDto.getUuid()) - ); + .setUuid(Uuids.createFast()) + .setUserUuid(user.getUuid()) + .setQualityGateUuid(qualityGateDto.getUuid()), + qualityGateDto.getName(), + user.getLogin()); dbSession.commit(); } } diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/AddGroupAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/AddGroupAction.java index 2924ac68ca9..06ed4bc9e61 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/AddGroupAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/AddGroupAction.java @@ -64,7 +64,9 @@ public class AddGroupAction extends AbstractGroupAction { new QualityGateGroupPermissionsDto() .setUuid(uuidFactory.create()) .setGroupUuid(group.getUuid()) - .setQualityGateUuid(qualityGate.getUuid())); + .setQualityGateUuid(qualityGate.getUuid()), + qualityGate.getName(), + group.getName()); dbSession.commit(); } diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/AddUserAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/AddUserAction.java index 6ce85ae1092..a5c0c44c06e 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/AddUserAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/ws/AddUserAction.java @@ -65,7 +65,7 @@ public class AddUserAction extends AbstractUserAction { new QualityGateUserPermissionsDto() .setUuid(uuidFactory.create()) .setUserUuid(user.getUuid()) - .setQualityGateUuid(qualityGate.getUuid())); + .setQualityGateUuid(qualityGate.getUuid()), qualityGate.getName(), user.getLogin()); dbSession.commit(); } -- 2.39.5