Skip to content

Commit

Permalink
SONAR-9018 Create a "members" group when creating an organization
Browse files Browse the repository at this point in the history
  • Loading branch information
julienlancelot committed Apr 13, 2017
1 parent 1e7edfd commit e8a1a4d
Show file tree
Hide file tree
Showing 11 changed files with 335 additions and 79 deletions.
Expand Up @@ -27,6 +27,7 @@
import org.sonar.db.DbSession;
import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.user.UserDto;
import org.sonar.server.usergroups.DefaultGroupCreatorImpl;

import static java.util.Objects.requireNonNull;

Expand All @@ -45,7 +46,8 @@ public interface OrganizationCreation {
* <ol>
* <li>create an ungarded organization with the specified details</li>
* <li>create a group called {@link #OWNERS_GROUP_NAME Owners} with all organization wide permissions</li>
* <li>make the specified user a member of this group</li>
* <li>create a group called {@link DefaultGroupCreatorImpl#DEFAULT_GROUP_NAME members} with browse permissions</li>
* <li>make the specified user a member of these groups</li>
* <li>create a default template for the organization
* <ul>
* <li>name is {@link #PERM_TEMPLATE_NAME Default template}</li>
Expand All @@ -57,8 +59,8 @@ public interface OrganizationCreation {
* <li>group {@link #OWNERS_GROUP_NAME Owners} : {@link UserRole#ADMIN ADMIN}</li>
* <li>group {@link #OWNERS_GROUP_NAME Owners} : {@link UserRole#ISSUE_ADMIN ISSUE_ADMIN}</li>
* <li>group {@link #OWNERS_GROUP_NAME Owners} : {@link GlobalPermissions#SCAN_EXECUTION SCAN_EXECUTION}</li>
* <li>anyone : {@link UserRole#USER USER}</li>
* <li>anyone : {@link UserRole#CODEVIEWER CODEVIEWER}</li>
* <li>group {@link DefaultGroupCreatorImpl#DEFAULT_GROUP_NAME members} : {@link UserRole#USER USER}</li>
* <li>group {@link DefaultGroupCreatorImpl#DEFAULT_GROUP_NAME members} : {@link UserRole#CODEVIEWER CODEVIEWER}</li>
* </ul>
* </li>
* </ol>
Expand Down Expand Up @@ -86,6 +88,8 @@ public interface OrganizationCreation {
* <li>url and avatar: null</li>
* </ul>
* </li>
* <li>create a group called {@link DefaultGroupCreatorImpl#DEFAULT_GROUP_NAME members} with browse permissions</li>
* <li>make the specified user a member of this group</li>
* <li>give all organization wide permissions to the user</li>
* <li>create a default template for the organization
* <ul>
Expand All @@ -99,8 +103,8 @@ public interface OrganizationCreation {
* <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>
* <li>group {@link DefaultGroupCreatorImpl#DEFAULT_GROUP_NAME members} : {@link UserRole#USER USER}</li>
* <li>group {@link DefaultGroupCreatorImpl#DEFAULT_GROUP_NAME members} : {@link UserRole#CODEVIEWER CODEVIEWER}</li>
* </ul>
* </li>
* </ol>
Expand Down
Expand Up @@ -29,9 +29,7 @@
import org.sonar.api.utils.System2;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.api.web.UserRole;
import org.sonar.core.config.CorePropertyDefinitions;
import org.sonar.core.permission.GlobalPermissions;
import org.sonar.core.util.UuidFactory;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
Expand All @@ -52,10 +50,16 @@
import org.sonar.server.qualityprofile.DefinedQProfileRepository;
import org.sonar.server.qualityprofile.index.ActiveRuleIndexer;
import org.sonar.server.user.index.UserIndexer;
import org.sonar.server.usergroups.DefaultGroupCreator;

import static com.google.common.base.Preconditions.checkState;
import static java.lang.String.format;
import static java.util.Objects.requireNonNull;
import static org.sonar.api.web.UserRole.ADMIN;
import static org.sonar.api.web.UserRole.CODEVIEWER;
import static org.sonar.api.web.UserRole.ISSUE_ADMIN;
import static org.sonar.api.web.UserRole.USER;
import static org.sonar.db.permission.OrganizationPermission.SCAN;
import static org.sonar.server.organization.OrganizationCreation.NewOrganization.newOrganizationBuilder;

public class OrganizationCreationImpl implements OrganizationCreation {
Expand All @@ -68,12 +72,14 @@ public class OrganizationCreationImpl implements OrganizationCreation {
private final Settings settings;
private final DefinedQProfileRepository definedQProfileRepository;
private final DefinedQProfileCreation definedQProfileCreation;
private final DefaultGroupCreator defaultGroupCreator;
private final ActiveRuleIndexer activeRuleIndexer;
private final UserIndexer userIndexer;

public OrganizationCreationImpl(DbClient dbClient, System2 system2, UuidFactory uuidFactory,
OrganizationValidation organizationValidation, Settings settings, UserIndexer userIndexer,
DefinedQProfileRepository definedQProfileRepository, DefinedQProfileCreation definedQProfileCreation, ActiveRuleIndexer activeRuleIndexer) {
DefinedQProfileRepository definedQProfileRepository, DefinedQProfileCreation definedQProfileCreation, DefaultGroupCreator defaultGroupCreator,
ActiveRuleIndexer activeRuleIndexer) {
this.dbClient = dbClient;
this.system2 = system2;
this.uuidFactory = uuidFactory;
Expand All @@ -82,6 +88,7 @@ public OrganizationCreationImpl(DbClient dbClient, System2 system2, UuidFactory
this.userIndexer = userIndexer;
this.definedQProfileRepository = definedQProfileRepository;
this.definedQProfileCreation = definedQProfileCreation;
this.defaultGroupCreator = defaultGroupCreator;
this.activeRuleIndexer = activeRuleIndexer;
}

Expand All @@ -96,10 +103,12 @@ public OrganizationDto create(DbSession dbSession, UserDto userCreator, NewOrgan
OrganizationDto organization = insertOrganization(dbSession, newOrganization, dto -> {
});
insertOrganizationMember(dbSession, organization, userCreator.getId());
GroupDto group = insertOwnersGroup(dbSession, organization);
insertDefaultTemplate(dbSession, organization, group);
GroupDto ownerGroup = insertOwnersGroup(dbSession, organization);
GroupDto defaultGroup = defaultGroupCreator.create(dbSession, organization.getUuid());
insertDefaultTemplateOnGroups(dbSession, organization, ownerGroup, defaultGroup);
List<ActiveRuleChange> activeRuleChanges = insertQualityProfiles(dbSession, organization);
addCurrentUserToGroup(dbSession, group, userCreator.getId());
addCurrentUserToGroup(dbSession, ownerGroup, userCreator.getId());
addCurrentUserToGroup(dbSession, defaultGroup, userCreator.getId());

dbSession.commit();

Expand Down Expand Up @@ -129,11 +138,13 @@ public Optional<OrganizationDto> createForUser(DbSession dbSession, UserDto newU

OrganizationDto organization = insertOrganization(dbSession, newOrganization,
dto -> dto.setGuarded(true).setUserId(newUser.getId()));
insertOrganizationMember(dbSession, organization, newUser.getId());
GroupDto defaultGroup = defaultGroupCreator.create(dbSession, organization.getUuid());
OrganizationPermission.all()
.forEach(p -> insertUserPermissions(dbSession, newUser, organization, p));
insertPersonalOrgDefaultTemplate(dbSession, organization);
insertOrganizationMember(dbSession, organization, newUser.getId());
insertPersonalOrgDefaultTemplate(dbSession, organization, defaultGroup);
List<ActiveRuleChange> activeRuleChanges = insertQualityProfiles(dbSession, organization);
addCurrentUserToGroup(dbSession, defaultGroup, newUser.getId());

dbSession.commit();

Expand Down Expand Up @@ -189,7 +200,7 @@ private boolean organizationKeyIsUsed(DbSession dbSession, String key) {
return dbClient.organizationDao().selectByKey(dbSession, key).isPresent();
}

private void insertDefaultTemplate(DbSession dbSession, OrganizationDto organizationDto, GroupDto group) {
private void insertDefaultTemplateOnGroups(DbSession dbSession, OrganizationDto organizationDto, GroupDto ownerGroup, GroupDto defaultGroup) {
Date now = new Date(system2.now());
PermissionTemplateDto permissionTemplateDto = dbClient.permissionTemplateDao().insert(
dbSession,
Expand All @@ -201,19 +212,19 @@ private void insertDefaultTemplate(DbSession dbSession, OrganizationDto organiza
.setCreatedAt(now)
.setUpdatedAt(now));

insertGroupPermission(dbSession, permissionTemplateDto, UserRole.ADMIN, group);
insertGroupPermission(dbSession, permissionTemplateDto, UserRole.ISSUE_ADMIN, group);
insertGroupPermission(dbSession, permissionTemplateDto, GlobalPermissions.SCAN_EXECUTION, group);
insertGroupPermission(dbSession, permissionTemplateDto, UserRole.USER, null);
insertGroupPermission(dbSession, permissionTemplateDto, UserRole.CODEVIEWER, null);
insertGroupPermission(dbSession, permissionTemplateDto, ADMIN, ownerGroup);
insertGroupPermission(dbSession, permissionTemplateDto, ISSUE_ADMIN, ownerGroup);
insertGroupPermission(dbSession, permissionTemplateDto, SCAN.getKey(), ownerGroup);
insertGroupPermission(dbSession, permissionTemplateDto, USER, defaultGroup);
insertGroupPermission(dbSession, permissionTemplateDto, CODEVIEWER, defaultGroup);

dbClient.organizationDao().setDefaultTemplates(
dbSession,
organizationDto.getUuid(),
new DefaultTemplates().setProjectUuid(permissionTemplateDto.getUuid()));
}

private void insertPersonalOrgDefaultTemplate(DbSession dbSession, OrganizationDto organizationDto) {
private void insertPersonalOrgDefaultTemplate(DbSession dbSession, OrganizationDto organizationDto, GroupDto defaultGroup) {
long now = system2.now();
Date dateNow = new Date(now);
PermissionTemplateDto permissionTemplateDto = dbClient.permissionTemplateDao().insert(
Expand All @@ -226,11 +237,11 @@ private void insertPersonalOrgDefaultTemplate(DbSession dbSession, OrganizationD
.setCreatedAt(dateNow)
.setUpdatedAt(dateNow));

insertProjectCreatorPermission(dbSession, permissionTemplateDto, UserRole.ADMIN, now);
insertProjectCreatorPermission(dbSession, permissionTemplateDto, UserRole.ISSUE_ADMIN, now);
insertProjectCreatorPermission(dbSession, permissionTemplateDto, OrganizationPermission.SCAN.getKey(), now);
insertGroupPermission(dbSession, permissionTemplateDto, UserRole.USER, null);
insertGroupPermission(dbSession, permissionTemplateDto, UserRole.CODEVIEWER, null);
insertProjectCreatorPermission(dbSession, permissionTemplateDto, ADMIN, now);
insertProjectCreatorPermission(dbSession, permissionTemplateDto, ISSUE_ADMIN, now);
insertProjectCreatorPermission(dbSession, permissionTemplateDto, SCAN.getKey(), now);
insertGroupPermission(dbSession, permissionTemplateDto, USER, defaultGroup);
insertGroupPermission(dbSession, permissionTemplateDto, CODEVIEWER, defaultGroup);

dbClient.organizationDao().setDefaultTemplates(
dbSession,
Expand Down
Expand Up @@ -20,7 +20,6 @@
package org.sonar.server.organization.ws;

import java.util.List;
import java.util.Optional;
import org.sonar.api.server.ws.Change;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
Expand All @@ -35,8 +34,8 @@
import org.sonar.server.organization.DefaultOrganizationProvider;
import org.sonar.server.organization.OrganizationFlags;
import org.sonar.server.user.UserSession;
import org.sonar.server.usergroups.DefaultGroupCreator;

import static com.google.common.base.Preconditions.checkArgument;
import static java.util.Objects.requireNonNull;

public class EnableSupportAction implements OrganizationsWsAction {
Expand All @@ -46,13 +45,15 @@ public class EnableSupportAction implements OrganizationsWsAction {
private final DbClient dbClient;
private final DefaultOrganizationProvider defaultOrganizationProvider;
private final OrganizationFlags organizationFlags;
private final DefaultGroupCreator defaultGroupCreator;

public EnableSupportAction(UserSession userSession, DbClient dbClient, DefaultOrganizationProvider defaultOrganizationProvider,
OrganizationFlags organizationFlags) {
OrganizationFlags organizationFlags, DefaultGroupCreator defaultGroupCreator) {
this.userSession = userSession;
this.dbClient = dbClient;
this.defaultOrganizationProvider = defaultOrganizationProvider;
this.organizationFlags = organizationFlags;
this.defaultGroupCreator = defaultGroupCreator;
}

@Override
Expand Down Expand Up @@ -96,20 +97,12 @@ private void flagCurrentUserAsRoot(DbSession dbSession) {

private void createDefaultMembersGroup(DbSession dbSession) {
String defaultOrganizationUuid = defaultOrganizationProvider.get().getUuid();
String membersGroupName = "Members";
Optional<GroupDto> existingMembersGroup = dbClient.groupDao().selectByName(dbSession, defaultOrganizationUuid, membersGroupName);
checkArgument(!existingMembersGroup.isPresent(), "The group '%s' already exist", membersGroupName);
GroupDto members = new GroupDto()
.setName(membersGroupName)
.setDescription("All members of the organization")
.setOrganizationUuid(defaultOrganizationUuid);
dbClient.groupDao().insert(dbSession, members);
int sonarUsersGroupId = dbClient.organizationDao().getDefaultGroupId(dbSession, defaultOrganizationUuid)
.orElseThrow(() -> new IllegalStateException(String.format("Default group doesn't exist on default organization '%s'", defaultOrganizationProvider.get().getKey())));
GroupDto members = defaultGroupCreator.create(dbSession, defaultOrganizationUuid);
copySonarUsersGroupPermissionsToMembersGroup(dbSession, sonarUsersGroupId, members);
copySonarUsersGroupPermissionTemplatesToMembersGroup(dbSession, sonarUsersGroupId, members);
associateMembersOfDefaultOrganizationToGroup(dbSession, members);
dbClient.organizationDao().setDefaultGroupId(dbSession, defaultOrganizationUuid, members);
}

private void associateMembersOfDefaultOrganizationToGroup(DbSession dbSession, GroupDto membersGroup) {
Expand Down
Expand Up @@ -206,6 +206,7 @@
import org.sonar.server.user.index.UserIndexDefinition;
import org.sonar.server.user.index.UserIndexer;
import org.sonar.server.user.ws.UsersWsModule;
import org.sonar.server.usergroups.DefaultGroupCreatorImpl;
import org.sonar.server.usergroups.ws.UserGroupsModule;
import org.sonar.server.usertoken.UserTokenModule;
import org.sonar.server.util.TypeValidationModule;
Expand Down Expand Up @@ -352,6 +353,7 @@ protected void configureLevel() {

// groups
UserGroupsModule.class,
DefaultGroupCreatorImpl.class,

// permissions
DefaultTemplatesResolverImpl.class,
Expand Down
@@ -0,0 +1,33 @@
/*
* SonarQube
* Copyright (C) 2009-2017 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.server.usergroups;

import org.sonar.db.DbSession;
import org.sonar.db.user.GroupDto;

public interface DefaultGroupCreator {

/**
* Create the default group on the given organization
*/
GroupDto create(DbSession dbSession, String organizationUuid);

}
@@ -0,0 +1,52 @@
/*
* SonarQube
* Copyright (C) 2009-2017 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.server.usergroups;

import java.util.Optional;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.user.GroupDto;

import static com.google.common.base.Preconditions.checkArgument;

public class DefaultGroupCreatorImpl implements DefaultGroupCreator {

static final String DEFAULT_GROUP_NAME = "Members";
private final DbClient dbClient;

public DefaultGroupCreatorImpl(DbClient dbClient) {
this.dbClient = dbClient;
}

public GroupDto create(DbSession dbSession, String organizationUuid) {
Optional<GroupDto> existingMembersGroup = dbClient.groupDao().selectByName(dbSession, organizationUuid, DEFAULT_GROUP_NAME);
checkArgument(!existingMembersGroup.isPresent(), "The group '%s' already exist on organization '%s'", DEFAULT_GROUP_NAME, organizationUuid);

GroupDto defaultGroup = new GroupDto()
.setName(DEFAULT_GROUP_NAME)
.setDescription("All members of the organization")
.setOrganizationUuid(organizationUuid);
dbClient.groupDao().insert(dbSession, defaultGroup);
dbClient.organizationDao().setDefaultGroupId(dbSession, organizationUuid, defaultGroup);
return defaultGroup;
}

}
@@ -0,0 +1,23 @@
/*
* SonarQube
* Copyright (C) 2009-2017 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.
*/
@ParametersAreNonnullByDefault
package org.sonar.server.usergroups;

import javax.annotation.ParametersAreNonnullByDefault;

0 comments on commit e8a1a4d

Please sign in to comment.