aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>2017-02-16 17:36:25 +0100
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>2017-02-17 15:47:10 +0100
commit011c3e3ae0bbf9ed9e9d0f75ce6d09da696c94fb (patch)
treec7c3895fc3df3a043ca6d92ec3c7c1fca8ac9973
parent9f5ad5ec0cadc465c61e9c6b3952753e4abfa91f (diff)
downloadsonarqube-011c3e3ae0bbf9ed9e9d0f75ce6d09da696c94fb.tar.gz
sonarqube-011c3e3ae0bbf9ed9e9d0f75ce6d09da696c94fb.zip
SONAR-8751 drop Owners group for personal organizations
user permissions replace group permissions in the default template and also SCAN permission is added to the template
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationCreation.java42
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationCreationImpl.java51
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/organization/OrganizationCreationImplTest.java96
3 files changed, 141 insertions, 48 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationCreation.java b/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationCreation.java
index 518fc0d3134..017ca85465b 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationCreation.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationCreation.java
@@ -23,6 +23,7 @@ import java.util.Optional;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.sonar.api.web.UserRole;
+import org.sonar.core.permission.GlobalPermissions;
import org.sonar.db.DbSession;
import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.user.UserDto;
@@ -32,6 +33,7 @@ import static java.util.Objects.requireNonNull;
public interface OrganizationCreation {
String OWNERS_GROUP_NAME = "Owners";
String OWNERS_GROUP_DESCRIPTION_PATTERN = "Owners of organization %s";
+ String PERM_TEMPLATE_NAME = "Default template";
String PERM_TEMPLATE_DESCRIPTION_PATTERN = "Default permission template of organization %s";
String PERSONAL_ORGANIZATION_DESCRIPTION_PATTERN = "%s's personal organization";
@@ -67,16 +69,36 @@ public interface OrganizationCreation {
/**
* Create a new guarded organization which details are based on the login of the specified User.
* <p>
- * This method create the organization and its associated elements in exactly the same was as
- * {@link #create(DbSession, long, NewOrganization)} with the organization's details computed from the
- * user's login:
- * <ul>
- * <li>key: generated from the user's login</li>
- * <li>name: the user's name if set, otherwise the user's login</li>
- * <li>description: {@link #PERSONAL_ORGANIZATION_DESCRIPTION_PATTERN "[name]'s personal organization"} where name
- * is user name (when non null and non empty) or login</li>
- * <li>url and avatar: null</li>
- * </ul>
+ * This method does several operations at once:
+ * <ol>
+ * <li>
+ * create a guarded organization with the details computed from user's details:
+ * <ul>
+ * <li>key: generated from the user's login</li>
+ * <li>name: the user's name if set, otherwise the user's login</li>
+ * <li>description: {@link #PERSONAL_ORGANIZATION_DESCRIPTION_PATTERN "[name]'s personal organization"} where name
+ * is user name (when non null and non empty) or login</li>
+ * <li>url and avatar: null</li>
+ * </ul>
+ * </li>
+ * <li>give all organization wide permissions to the user</li>
+ * <li>create a default template for the organization
+ * <ul>
+ * <li>name is {@link #PERM_TEMPLATE_NAME Default template}</li>
+ * <li>description follows pattern {@link #PERM_TEMPLATE_DESCRIPTION_PATTERN} based on the organization name</li>
+ * </ul>
+ * </li>
+ * <li>this permission template defines the specified permissions (which effectively makes projects public and
+ * automatically adds new projects to the user's favorites):
+ * <ul>
+ * <li>project creator : {@link UserRole#ADMIN ADMIN}</li>
+ * <li>project creator : {@link UserRole#ISSUE_ADMIN ISSUE_ADMIN}</li>
+ * <li>project creator : {@link GlobalPermissions#SCAN_EXECUTION SCAN_EXECUTION}</li>
+ * <li>anyone : {@link UserRole#USER USER}</li>
+ * <li>anyone : {@link UserRole#CODEVIEWER CODEVIEWER}</li>
+ * </ul>
+ * </li>
+ * </ol>
* </p>
*
* @return the created organization or empty if feature is disabled
diff --git a/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationCreationImpl.java b/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationCreationImpl.java
index c5333acf0d0..849ebf69f4b 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationCreationImpl.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationCreationImpl.java
@@ -34,6 +34,8 @@ import org.sonar.db.DbSession;
import org.sonar.db.organization.DefaultTemplates;
import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.permission.GroupPermissionDto;
+import org.sonar.db.permission.UserPermissionDto;
+import org.sonar.db.permission.template.PermissionTemplateCharacteristicDto;
import org.sonar.db.permission.template.PermissionTemplateDto;
import org.sonar.db.user.GroupDto;
import org.sonar.db.user.UserDto;
@@ -99,9 +101,8 @@ public class OrganizationCreationImpl implements OrganizationCreation {
OrganizationDto organization = insertOrganization(dbSession, newOrganization,
dto -> dto.setGuarded(true).setUserId(newUser.getId()));
- GroupDto group = insertOwnersGroup(dbSession, organization);
- insertDefaultTemplate(dbSession, organization, group);
- addCurrentUserToGroup(dbSession, group, newUser.getId());
+ GlobalPermissions.ALL.forEach(permission -> insertUserPermissions(dbSession, newUser, organization, permission));
+ insertPersonalOrgDefaultTemplate(dbSession, organization);
dbSession.commit();
@@ -160,7 +161,7 @@ public class OrganizationCreationImpl implements OrganizationCreation {
new PermissionTemplateDto()
.setOrganizationUuid(organizationDto.getUuid())
.setUuid(uuidFactory.create())
- .setName("Default template")
+ .setName(PERM_TEMPLATE_NAME)
.setDescription(format(PERM_TEMPLATE_DESCRIPTION_PATTERN, organizationDto.getName()))
.setCreatedAt(now)
.setUpdatedAt(now));
@@ -176,6 +177,42 @@ public class OrganizationCreationImpl implements OrganizationCreation {
new DefaultTemplates().setProjectUuid(permissionTemplateDto.getUuid()));
}
+ private void insertPersonalOrgDefaultTemplate(DbSession dbSession, OrganizationDto organizationDto) {
+ long now = system2.now();
+ Date dateNow = new Date(now);
+ PermissionTemplateDto permissionTemplateDto = dbClient.permissionTemplateDao().insert(
+ dbSession,
+ new PermissionTemplateDto()
+ .setOrganizationUuid(organizationDto.getUuid())
+ .setUuid(uuidFactory.create())
+ .setName("Default template")
+ .setDescription(format(PERM_TEMPLATE_DESCRIPTION_PATTERN, organizationDto.getName()))
+ .setCreatedAt(dateNow)
+ .setUpdatedAt(dateNow));
+
+ insertProjectCreatorPermission(dbSession, permissionTemplateDto, UserRole.ADMIN, now);
+ insertProjectCreatorPermission(dbSession, permissionTemplateDto, UserRole.ISSUE_ADMIN, now);
+ insertProjectCreatorPermission(dbSession, permissionTemplateDto, GlobalPermissions.SCAN_EXECUTION, now);
+ insertGroupPermission(dbSession, permissionTemplateDto, UserRole.USER, null);
+ insertGroupPermission(dbSession, permissionTemplateDto, UserRole.CODEVIEWER, null);
+
+ dbClient.organizationDao().setDefaultTemplates(
+ dbSession,
+ organizationDto.getUuid(),
+ new DefaultTemplates().setProjectUuid(permissionTemplateDto.getUuid()));
+ }
+
+ private void insertProjectCreatorPermission(DbSession dbSession, PermissionTemplateDto permissionTemplateDto, String permission, long now) {
+ dbClient.permissionTemplateCharacteristicDao().insert(
+ dbSession,
+ new PermissionTemplateCharacteristicDto()
+ .setTemplateId(permissionTemplateDto.getId())
+ .setWithProjectCreator(true)
+ .setPermission(permission)
+ .setCreatedAt(now)
+ .setUpdatedAt(now));
+ }
+
private void insertGroupPermission(DbSession dbSession, PermissionTemplateDto template, String permission, @Nullable GroupDto group) {
dbClient.permissionTemplateDao().insertGroupPermission(dbSession, template.getId(), group == null ? null : group.getId(), permission);
}
@@ -201,6 +238,12 @@ public class OrganizationCreationImpl implements OrganizationCreation {
.setRole(permission));
}
+ private void insertUserPermissions(DbSession dbSession, UserDto userDto, OrganizationDto organization, String permission) {
+ dbClient.userPermissionDao().insert(
+ dbSession,
+ new UserPermissionDto(organization.getUuid(), permission, userDto.getId(), null));
+ }
+
private void addCurrentUserToGroup(DbSession dbSession, GroupDto group, long createUserId) {
dbClient.userGroupDao().insert(
dbSession,
diff --git a/server/sonar-server/src/test/java/org/sonar/server/organization/OrganizationCreationImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/organization/OrganizationCreationImplTest.java
index 4ebeec9bb31..5afe163a4da 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/organization/OrganizationCreationImplTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/organization/OrganizationCreationImplTest.java
@@ -19,8 +19,8 @@
*/
package org.sonar.server.organization;
+import java.util.Collections;
import java.util.List;
-import java.util.Optional;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
@@ -35,6 +35,7 @@ import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
import org.sonar.db.organization.DefaultTemplates;
import org.sonar.db.organization.OrganizationDto;
+import org.sonar.db.permission.template.PermissionTemplateCharacteristicDto;
import org.sonar.db.permission.template.PermissionTemplateDto;
import org.sonar.db.permission.template.PermissionTemplateGroupDto;
import org.sonar.db.user.GroupDto;
@@ -57,14 +58,15 @@ public class OrganizationCreationImplTest {
private static final String SLUG_OF_A_LOGIN = "slug-of-a-login";
private static final String STRING_64_CHARS = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
private static final String A_NAME = "a name";
+ private static final long ANYONE_GROUP_ID = 0L;
private OrganizationCreation.NewOrganization FULL_POPULATED_NEW_ORGANIZATION = newOrganizationBuilder()
- .setName("a-name")
- .setKey("a-key")
- .setDescription("a-description")
- .setUrl("a-url")
- .setAvatarUrl("a-avatar")
- .build();
+ .setName("a-name")
+ .setKey("a-key")
+ .setDescription("a-description")
+ .setUrl("a-url")
+ .setAvatarUrl("a-avatar")
+ .build();
private System2 system2 = mock(System2.class);
@@ -94,7 +96,7 @@ public class OrganizationCreationImplTest {
@Test
public void create_throws_exception_thrown_by_checkValidKey() throws OrganizationCreation.KeyConflictException {
when(organizationValidation.checkKey(FULL_POPULATED_NEW_ORGANIZATION.getKey()))
- .thenThrow(exceptionThrownByOrganizationValidation);
+ .thenThrow(exceptionThrownByOrganizationValidation);
createThrowsExceptionThrownByOrganizationValidation();
}
@@ -174,9 +176,9 @@ public class OrganizationCreationImplTest {
mockForSuccessfulInsert(SOME_UUID, SOME_DATE);
underTest.create(dbSession, SOME_USER_ID, newOrganizationBuilder()
- .setKey("key")
- .setName("name")
- .build());
+ .setKey("key")
+ .setName("name")
+ .build());
OrganizationDto organization = dbClient.organizationDao().selectByKey(dbSession, "key").get();
assertThat(organization.getKey()).isEqualTo("key");
@@ -194,7 +196,19 @@ public class OrganizationCreationImplTest {
underTest.create(dbSession, SOME_USER_ID, FULL_POPULATED_NEW_ORGANIZATION);
- verifyDefaultTemplate(FULL_POPULATED_NEW_ORGANIZATION.getKey(), FULL_POPULATED_NEW_ORGANIZATION.getName());
+ OrganizationDto organization = dbClient.organizationDao().selectByKey(dbSession, FULL_POPULATED_NEW_ORGANIZATION.getKey()).get();
+ GroupDto ownersGroup = dbClient.groupDao().selectByName(dbSession, organization.getUuid(), "Owners").get();
+ PermissionTemplateDto defaultTemplate = dbClient.permissionTemplateDao().selectByName(dbSession, organization.getUuid(), "default template");
+ assertThat(defaultTemplate.getName()).isEqualTo("Default template");
+ assertThat(defaultTemplate.getDescription()).isEqualTo("Default permission template of organization " + FULL_POPULATED_NEW_ORGANIZATION.getName());
+ DefaultTemplates defaultTemplates = dbClient.organizationDao().getDefaultTemplates(dbSession, organization.getUuid()).get();
+ assertThat(defaultTemplates.getProjectUuid()).isEqualTo(defaultTemplate.getUuid());
+ assertThat(defaultTemplates.getViewUuid()).isNull();
+ assertThat(dbClient.permissionTemplateDao().selectGroupPermissionsByTemplateId(dbSession, defaultTemplate.getId()))
+ .extracting(PermissionTemplateGroupDto::getGroupId, PermissionTemplateGroupDto::getPermission)
+ .containsOnly(
+ tuple(ownersGroup.getId(), UserRole.ADMIN), tuple(ownersGroup.getId(), UserRole.ISSUE_ADMIN),
+ tuple(ANYONE_GROUP_ID, UserRole.USER), tuple(ANYONE_GROUP_ID, UserRole.CODEVIEWER));
}
@Test
@@ -258,13 +272,13 @@ public class OrganizationCreationImplTest {
expectedException.expect(IllegalStateException.class);
expectedException.expectMessage("Can't create organization with key '" + SLUG_OF_A_LOGIN + "' for new user '" + A_LOGIN
- + "' because an organization with this key already exists");
+ + "' because an organization with this key already exists");
underTest.createForUser(dbSession, user);
}
@Test
- public void createForUser_creates_owners_group_with_all_permissions_for_new_organization_and_add_current_user_to_it() throws OrganizationCreation.KeyConflictException {
+ public void createForUser_gives_all_permissions_for_new_organization_to_current_user() throws OrganizationCreation.KeyConflictException {
UserDto user = dbTester.users().insertUser(dto -> dto.setLogin(A_LOGIN).setName(A_NAME));
when(organizationValidation.generateKeyFrom(A_LOGIN)).thenReturn(SLUG_OF_A_LOGIN);
mockForSuccessfulInsert(SOME_UUID, SOME_DATE);
@@ -272,23 +286,40 @@ public class OrganizationCreationImplTest {
underTest.createForUser(dbSession, user);
- verifyGroupOwners(user, SLUG_OF_A_LOGIN, A_NAME);
+ OrganizationDto organization = dbClient.organizationDao().selectByKey(dbSession, SLUG_OF_A_LOGIN).get();
+ assertThat(dbClient.userPermissionDao().selectGlobalPermissionsOfUser(dbSession, user.getId(), organization.getUuid()))
+ .containsOnly(GlobalPermissions.ALL.toArray(new String[GlobalPermissions.ALL.size()]));
+ }
+
+ @Test
+ public void createForUser_does_not_create_any_group() throws OrganizationCreation.KeyConflictException {
+ UserDto user = dbTester.users().insertUser(dto -> dto.setLogin(A_LOGIN).setName(A_NAME));
+ when(organizationValidation.generateKeyFrom(A_LOGIN)).thenReturn(SLUG_OF_A_LOGIN);
+ mockForSuccessfulInsert(SOME_UUID, SOME_DATE);
+ enableCreatePersonalOrg(true);
+
+ underTest.createForUser(dbSession, user);
+
+ OrganizationDto organization = dbClient.organizationDao().selectByKey(dbSession, SLUG_OF_A_LOGIN).get();
+ assertThat(dbClient.groupDao().selectByOrganizationUuid(dbSession, organization.getUuid())).isEmpty();
}
private void verifyGroupOwners(UserDto user, String organizationKey, String organizationName) {
OrganizationDto organization = dbClient.organizationDao().selectByKey(dbSession, organizationKey).get();
- Optional<GroupDto> groupDtoOptional = dbClient.groupDao().selectByName(dbSession, organization.getUuid(), "Owners");
- assertThat(groupDtoOptional).isNotEmpty();
- GroupDto groupDto = groupDtoOptional.get();
+ List<GroupDto> groups = dbClient.groupDao().selectByOrganizationUuid(dbSession, organization.getUuid());
+ assertThat(groups)
+ .extracting(GroupDto::getName)
+ .containsOnly("Owners");
+ GroupDto groupDto = groups.iterator().next();
assertThat(groupDto.getDescription()).isEqualTo("Owners of organization " + organizationName);
assertThat(dbClient.groupPermissionDao().selectGlobalPermissionsOfGroup(dbSession, groupDto.getOrganizationUuid(), groupDto.getId()))
- .containsOnly(GlobalPermissions.ALL.toArray(new String[GlobalPermissions.ALL.size()]));
+ .containsOnly(GlobalPermissions.ALL.toArray(new String[GlobalPermissions.ALL.size()]));
List<UserMembershipDto> members = dbClient.groupMembershipDao().selectMembers(
- dbSession,
- UserMembershipQuery.builder().groupId(groupDto.getId()).membership(UserMembershipQuery.IN).build(), 0, Integer.MAX_VALUE);
+ dbSession,
+ UserMembershipQuery.builder().groupId(groupDto.getId()).membership(UserMembershipQuery.IN).build(), 0, Integer.MAX_VALUE);
assertThat(members)
- .extracting(UserMembershipDto::getLogin)
- .containsOnly(user.getLogin());
+ .extracting(UserMembershipDto::getLogin)
+ .containsOnly(user.getLogin());
}
@Test
@@ -300,23 +331,20 @@ public class OrganizationCreationImplTest {
underTest.createForUser(dbSession, user);
- verifyDefaultTemplate(SLUG_OF_A_LOGIN, A_NAME);
- }
-
- private void verifyDefaultTemplate(String organizationKey, String organizationName) {
- OrganizationDto organization = dbClient.organizationDao().selectByKey(dbSession, organizationKey).get();
- GroupDto ownersGroup = dbClient.groupDao().selectByName(dbSession, organization.getUuid(), "Owners").get();
+ OrganizationDto organization = dbClient.organizationDao().selectByKey(dbSession, SLUG_OF_A_LOGIN).get();
PermissionTemplateDto defaultTemplate = dbClient.permissionTemplateDao().selectByName(dbSession, organization.getUuid(), "default template");
assertThat(defaultTemplate.getName()).isEqualTo("Default template");
- assertThat(defaultTemplate.getDescription()).isEqualTo("Default permission template of organization " + organizationName);
+ assertThat(defaultTemplate.getDescription()).isEqualTo("Default permission template of organization " + A_NAME);
DefaultTemplates defaultTemplates = dbClient.organizationDao().getDefaultTemplates(dbSession, organization.getUuid()).get();
assertThat(defaultTemplates.getProjectUuid()).isEqualTo(defaultTemplate.getUuid());
assertThat(defaultTemplates.getViewUuid()).isNull();
assertThat(dbClient.permissionTemplateDao().selectGroupPermissionsByTemplateId(dbSession, defaultTemplate.getId()))
- .extracting(PermissionTemplateGroupDto::getGroupId, PermissionTemplateGroupDto::getPermission)
- .containsOnly(
- tuple(ownersGroup.getId(), UserRole.ADMIN), tuple(ownersGroup.getId(), UserRole.ISSUE_ADMIN),
- tuple(0L, UserRole.USER), tuple(0L, UserRole.CODEVIEWER));
+ .extracting(PermissionTemplateGroupDto::getGroupId, PermissionTemplateGroupDto::getPermission)
+ .containsOnly(tuple(ANYONE_GROUP_ID, UserRole.USER), tuple(ANYONE_GROUP_ID, UserRole.CODEVIEWER));
+ assertThat(dbClient.permissionTemplateCharacteristicDao().selectByTemplateIds(dbSession, Collections.singletonList(defaultTemplate.getId())))
+ .extracting(PermissionTemplateCharacteristicDto::getWithProjectCreator, PermissionTemplateCharacteristicDto::getPermission)
+ .containsOnly(
+ tuple(true, UserRole.ADMIN), tuple(true, UserRole.ISSUE_ADMIN), tuple(true, GlobalPermissions.SCAN_EXECUTION));
}
@Test