From 8ac59775a18a51dc5712ece11635347a8519427c Mon Sep 17 00:00:00 2001 From: Jacek Date: Thu, 17 Dec 2020 12:09:24 +0100 Subject: [PATCH] SONAR-13999 drop more organization utility classes --- .../organization/OrganizationAlmBinding.java | 30 -- .../organization/OrganizationUpdater.java | 180 ---------- .../organization/OrganizationUpdaterImpl.java | 240 ------------- .../organization/OrganizationValidation.java | 107 ------ .../OrganizationValidationImpl.java | 83 ----- .../OrganizationUpdaterImplTest.java | 336 ------------------ .../OrganizationValidationImplTest.java | 240 ------------- .../ws/OrganizationsWsModule.java | 1 - .../ws/OrganizationsWsSupport.java | 131 ------- .../organization/ws/SearchMembersAction.java | 4 +- .../platformlevel/PlatformLevel4.java | 4 - 11 files changed, 2 insertions(+), 1354 deletions(-) delete mode 100644 server/sonar-webserver-auth/src/main/java/org/sonar/server/organization/OrganizationAlmBinding.java delete mode 100644 server/sonar-webserver-auth/src/main/java/org/sonar/server/organization/OrganizationUpdater.java delete mode 100644 server/sonar-webserver-auth/src/main/java/org/sonar/server/organization/OrganizationUpdaterImpl.java delete mode 100644 server/sonar-webserver-auth/src/main/java/org/sonar/server/organization/OrganizationValidation.java delete mode 100644 server/sonar-webserver-auth/src/main/java/org/sonar/server/organization/OrganizationValidationImpl.java delete mode 100644 server/sonar-webserver-auth/src/test/java/org/sonar/server/organization/OrganizationUpdaterImplTest.java delete mode 100644 server/sonar-webserver-auth/src/test/java/org/sonar/server/organization/OrganizationValidationImplTest.java delete mode 100644 server/sonar-webserver-webapi/src/main/java/org/sonar/server/organization/ws/OrganizationsWsSupport.java diff --git a/server/sonar-webserver-auth/src/main/java/org/sonar/server/organization/OrganizationAlmBinding.java b/server/sonar-webserver-auth/src/main/java/org/sonar/server/organization/OrganizationAlmBinding.java deleted file mode 100644 index ac8fbb9ca7a..00000000000 --- a/server/sonar-webserver-auth/src/main/java/org/sonar/server/organization/OrganizationAlmBinding.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2020 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.organization; - -import org.sonar.api.server.ServerSide; -import org.sonar.db.DbSession; -import org.sonar.db.organization.OrganizationDto; - -@ServerSide -public interface OrganizationAlmBinding { - - void bindOrganization(DbSession dbSession, OrganizationDto organization, String installationId, boolean isNewOrganization); -} diff --git a/server/sonar-webserver-auth/src/main/java/org/sonar/server/organization/OrganizationUpdater.java b/server/sonar-webserver-auth/src/main/java/org/sonar/server/organization/OrganizationUpdater.java deleted file mode 100644 index 913db0fb233..00000000000 --- a/server/sonar-webserver-auth/src/main/java/org/sonar/server/organization/OrganizationUpdater.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2020 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.organization; - -import java.util.function.Consumer; -import javax.annotation.CheckForNull; -import javax.annotation.Nullable; -import org.sonar.api.web.UserRole; -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; - -public interface OrganizationUpdater { - String OWNERS_GROUP_NAME = "Owners"; - String OWNERS_GROUP_DESCRIPTION = "Owners of organization"; - String PERM_TEMPLATE_NAME = "Default template"; - String PERM_TEMPLATE_DESCRIPTION_PATTERN = "Default permission template of organization %s"; - - /** - * Create a new organization with the specified properties and of which the specified user will assign - * Administer Organization permission. - *

- * This method does several operations at once: - *

    - *
  1. create an ungarded organization with the specified details
  2. - *
  3. create a group called {@link #OWNERS_GROUP_NAME Owners} with all organization wide permissions
  4. - *
  5. create a group called {@link DefaultGroupCreatorImpl#DEFAULT_GROUP_NAME members} with browse permissions
  6. - *
  7. make the specified user a member of these groups
  8. - *
  9. create a default template for the organization - *
      - *
    • name is {@link #PERM_TEMPLATE_NAME Default template}
    • - *
    • description follows pattern {@link #PERM_TEMPLATE_DESCRIPTION_PATTERN} based on the organization name
    • - *
    - *
  10. - *
  11. this permission template defines the specified permissions (which effectively makes projects public): - *
      - *
    • group {@link #OWNERS_GROUP_NAME Owners} : {@link UserRole#ADMIN ADMIN}
    • - *
    • group {@link #OWNERS_GROUP_NAME Owners} : {@link UserRole#ISSUE_ADMIN ISSUE_ADMIN}
    • - *
    • group {@link #OWNERS_GROUP_NAME Owners} : {@link UserRole#SECURITYHOTSPOT_ADMIN SECURITYHOTSPOT_ADMIN}
    • - *
    • group {@link #OWNERS_GROUP_NAME Owners} : {@link UserRole#SCAN SCAN}
    • - *
    • group {@link DefaultGroupCreatorImpl#DEFAULT_GROUP_NAME members} : {@link UserRole#USER USER}
    • - *
    • group {@link DefaultGroupCreatorImpl#DEFAULT_GROUP_NAME members} : {@link UserRole#CODEVIEWER CODEVIEWER}
    • - *
    - *
  12. - *
- *

- * - * @return the created organization - * - * @throws KeyConflictException if an organization with the specified key already exists - * @throws IllegalArgumentException if any field of {@code newOrganization} is invalid according to {@link OrganizationValidation} - */ - OrganizationDto create(DbSession dbSession, UserDto userCreator, NewOrganization newOrganization, Consumer beforeCommit) throws KeyConflictException; - - /** - * Update the personal organization key of a user. - * No update will be performed if generated key match the same key as existing one. - * - * @throws IllegalStateException if user has no no personal organization - * @throws IllegalStateException if personal organization uuid does not exist - * @throws IllegalStateException if an organization with the key generated from the login already exists - */ - void updateOrganizationKey(DbSession dbSession, OrganizationDto organization, String newKey); - - final class KeyConflictException extends Exception { - KeyConflictException(String message) { - super(message); - } - } - - final class NewOrganization { - private final String key; - private final String name; - @CheckForNull - private final String description; - @CheckForNull - private final String url; - @CheckForNull - private final String avatar; - - private NewOrganization(Builder builder) { - this.key = builder.key; - this.name = builder.name; - this.description = builder.description; - this.url = builder.url; - this.avatar = builder.avatarUrl; - } - - public String getKey() { - return key; - } - - public String getName() { - return name; - } - - @CheckForNull - public String getDescription() { - return description; - } - - @CheckForNull - public String getUrl() { - return url; - } - - @CheckForNull - public String getAvatar() { - return avatar; - } - - public static NewOrganization.Builder newOrganizationBuilder() { - return new Builder(); - } - - public static final class Builder { - private String key; - private String name; - private String description; - private String url; - private String avatarUrl; - - private Builder() { - // use factory method - } - - public Builder setKey(String key) { - this.key = requireNonNull(key, "key can't be null"); - return this; - } - - public Builder setName(String name) { - this.name = requireNonNull(name, "name can't be null"); - return this; - } - - public Builder setDescription(@Nullable String description) { - this.description = description; - return this; - } - - public Builder setUrl(@Nullable String url) { - this.url = url; - return this; - } - - public Builder setAvatarUrl(@Nullable String avatarUrl) { - this.avatarUrl = avatarUrl; - return this; - } - - public NewOrganization build() { - requireNonNull(key, "key can't be null"); - requireNonNull(name, "name can't be null"); - return new NewOrganization(this); - } - } - } - -} diff --git a/server/sonar-webserver-auth/src/main/java/org/sonar/server/organization/OrganizationUpdaterImpl.java b/server/sonar-webserver-auth/src/main/java/org/sonar/server/organization/OrganizationUpdaterImpl.java deleted file mode 100644 index f321b6be737..00000000000 --- a/server/sonar-webserver-auth/src/main/java/org/sonar/server/organization/OrganizationUpdaterImpl.java +++ /dev/null @@ -1,240 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2020 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.organization; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.function.Consumer; -import javax.annotation.Nullable; -import org.sonar.api.utils.System2; -import org.sonar.core.util.UuidFactory; -import org.sonar.db.DbClient; -import org.sonar.db.DbSession; -import org.sonar.db.organization.OrganizationDto; -import org.sonar.db.permission.GlobalPermission; -import org.sonar.db.permission.GroupPermissionDto; -import org.sonar.db.permission.template.DefaultTemplates; -import org.sonar.db.permission.template.PermissionTemplateDto; -import org.sonar.db.qualitygate.QualityGateDto; -import org.sonar.db.qualityprofile.DefaultQProfileDto; -import org.sonar.db.qualityprofile.OrgQProfileDto; -import org.sonar.db.user.GroupDto; -import org.sonar.db.user.UserDto; -import org.sonar.db.user.UserGroupDto; -import org.sonar.server.permission.PermissionService; -import org.sonar.server.qualityprofile.BuiltInQProfile; -import org.sonar.server.qualityprofile.BuiltInQProfileRepository; -import org.sonar.server.qualityprofile.QProfileName; -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.SECURITYHOTSPOT_ADMIN; -import static org.sonar.api.web.UserRole.USER; -import static org.sonar.core.util.stream.MoreCollectors.uniqueIndex; -import static org.sonar.db.organization.OrganizationDto.Subscription.FREE; -import static org.sonar.db.permission.GlobalPermission.SCAN; - -// TODO remove -@Deprecated -public class OrganizationUpdaterImpl implements OrganizationUpdater { - - private final DbClient dbClient; - private final System2 system2; - private final UuidFactory uuidFactory; - private final OrganizationValidation organizationValidation; - private final BuiltInQProfileRepository builtInQProfileRepository; - private final DefaultGroupCreator defaultGroupCreator; - private final UserIndexer userIndexer; - private final PermissionService permissionService; - - public OrganizationUpdaterImpl(DbClient dbClient, System2 system2, UuidFactory uuidFactory, - OrganizationValidation organizationValidation, UserIndexer userIndexer, - BuiltInQProfileRepository builtInQProfileRepository, DefaultGroupCreator defaultGroupCreator, PermissionService permissionService) { - this.dbClient = dbClient; - this.system2 = system2; - this.uuidFactory = uuidFactory; - this.organizationValidation = organizationValidation; - this.userIndexer = userIndexer; - this.builtInQProfileRepository = builtInQProfileRepository; - this.defaultGroupCreator = defaultGroupCreator; - this.permissionService = permissionService; - } - - @Override - public OrganizationDto create(DbSession dbSession, UserDto userCreator, NewOrganization newOrganization, Consumer beforeCommit) throws KeyConflictException { - validate(newOrganization); - String key = newOrganization.getKey(); - if (organizationKeyIsUsed(dbSession, key)) { - throw new KeyConflictException(format("Organization key '%s' is already used", key)); - } - - QualityGateDto builtInQualityGate = dbClient.qualityGateDao().selectBuiltIn(dbSession); - OrganizationDto organization = insertOrganization(dbSession, newOrganization, builtInQualityGate); - beforeCommit.accept(organization); - GroupDto ownerGroup = insertOwnersGroup(dbSession); - GroupDto defaultGroup = defaultGroupCreator.create(dbSession); - insertDefaultTemplateOnGroups(dbSession, organization, ownerGroup, defaultGroup); - addCurrentUserToGroup(dbSession, ownerGroup, userCreator.getUuid()); - addCurrentUserToGroup(dbSession, defaultGroup, userCreator.getUuid()); - try (DbSession batchDbSession = dbClient.openSession(true)) { - insertQualityProfiles(dbSession, batchDbSession); - batchDbSession.commit(); - - // Elasticsearch is updated when DB session is committed - userIndexer.commitAndIndex(dbSession, userCreator); - - return organization; - } - } - - @Override - public void updateOrganizationKey(DbSession dbSession, OrganizationDto organization, String newKey) { - String sanitizedKey = organizationValidation.generateKeyFrom(newKey); - if (organization.getKey().equals(sanitizedKey)) { - return; - } - checkKey(dbSession, sanitizedKey); - dbClient.organizationDao().update(dbSession, organization.setKey(sanitizedKey)); - } - - private void checkKey(DbSession dbSession, String key) { - checkState(!organizationKeyIsUsed(dbSession, key), - "Can't create organization with key '%s' because an organization with this key already exists", key); - } - - private void validate(NewOrganization newOrganization) { - requireNonNull(newOrganization, "newOrganization can't be null"); - organizationValidation.checkName(newOrganization.getName()); - organizationValidation.checkKey(newOrganization.getKey()); - organizationValidation.checkDescription(newOrganization.getDescription()); - organizationValidation.checkUrl(newOrganization.getUrl()); - organizationValidation.checkAvatar(newOrganization.getAvatar()); - } - - private OrganizationDto insertOrganization(DbSession dbSession, NewOrganization newOrganization, QualityGateDto builtInQualityGate, Consumer... extendCreation) { - OrganizationDto res = new OrganizationDto() - .setUuid(uuidFactory.create()) - .setName(newOrganization.getName()) - .setKey(newOrganization.getKey()) - .setDescription(newOrganization.getDescription()) - .setUrl(newOrganization.getUrl()) - .setDefaultQualityGateUuid(builtInQualityGate.getUuid()) - .setAvatarUrl(newOrganization.getAvatar()) - .setSubscription(FREE); - Arrays.stream(extendCreation).forEach(c -> c.accept(res)); - dbClient.organizationDao().insert(dbSession, res, false); - return res; - } - - private boolean organizationKeyIsUsed(DbSession dbSession, String key) { - return dbClient.organizationDao().selectByKey(dbSession, key).isPresent(); - } - - private void insertDefaultTemplateOnGroups(DbSession dbSession, OrganizationDto organizationDto, GroupDto ownerGroup, GroupDto defaultGroup) { - Date now = new Date(system2.now()); - PermissionTemplateDto permissionTemplateDto = dbClient.permissionTemplateDao().insert( - dbSession, - new PermissionTemplateDto() - .setUuid(uuidFactory.create()) - .setName(PERM_TEMPLATE_NAME) - .setDescription(format(PERM_TEMPLATE_DESCRIPTION_PATTERN, organizationDto.getName())) - .setCreatedAt(now) - .setUpdatedAt(now)); - - insertGroupPermission(dbSession, permissionTemplateDto, ADMIN, ownerGroup); - insertGroupPermission(dbSession, permissionTemplateDto, SCAN.getKey(), ownerGroup); - insertGroupPermission(dbSession, permissionTemplateDto, USER, defaultGroup); - insertGroupPermission(dbSession, permissionTemplateDto, CODEVIEWER, defaultGroup); - insertGroupPermission(dbSession, permissionTemplateDto, ISSUE_ADMIN, defaultGroup); - insertGroupPermission(dbSession, permissionTemplateDto, SECURITYHOTSPOT_ADMIN, defaultGroup); - - dbClient.organizationDao().setDefaultTemplates( - dbSession, - organizationDto.getUuid(), - new DefaultTemplates().setProjectUuid(permissionTemplateDto.getUuid())); - } - - private void insertGroupPermission(DbSession dbSession, PermissionTemplateDto template, String permission, @Nullable GroupDto group) { - dbClient.permissionTemplateDao().insertGroupPermission(dbSession, template.getUuid(), group == null ? null : group.getUuid(), permission); - } - - private void insertQualityProfiles(DbSession dbSession, DbSession batchDbSession) { - Map builtInsPerName = builtInQProfileRepository.get().stream() - .collect(uniqueIndex(BuiltInQProfile::getQProfileName)); - - List defaults = new ArrayList<>(); - dbClient.qualityProfileDao().selectBuiltInRuleProfiles(dbSession).forEach(rulesProfile -> { - OrgQProfileDto dto = new OrgQProfileDto() - .setRulesProfileUuid(rulesProfile.getUuid()) - .setUuid(uuidFactory.create()); - - QProfileName name = new QProfileName(rulesProfile.getLanguage(), rulesProfile.getName()); - BuiltInQProfile builtIn = builtInsPerName.get(name); - if (builtIn == null || builtIn.isDefault()) { - // If builtIn == null, the plugin has been removed - // rows of table default_qprofiles must be inserted after org_qprofiles - // in order to benefit from batch SQL inserts - defaults.add(new DefaultQProfileDto() - .setQProfileUuid(dto.getUuid()) - .setLanguage(rulesProfile.getLanguage())); - } - - dbClient.qualityProfileDao().insert(batchDbSession, dto); - }); - - defaults.forEach(defaultQProfileDto -> dbClient.defaultQProfileDao().insertOrUpdate(dbSession, defaultQProfileDto)); - } - - /** - * Owners group has an hard coded name, a description based on the organization's name and has all global permissions. - */ - private GroupDto insertOwnersGroup(DbSession dbSession) { - GroupDto group = dbClient.groupDao().insert(dbSession, new GroupDto() - .setUuid(uuidFactory.create()) - .setName(OWNERS_GROUP_NAME) - .setDescription(OWNERS_GROUP_DESCRIPTION)); - permissionService.getGlobalPermissions().forEach(p -> addPermissionToGroup(dbSession, group, p)); - return group; - } - - private void addPermissionToGroup(DbSession dbSession, GroupDto group, GlobalPermission permission) { - dbClient.groupPermissionDao().insert( - dbSession, - new GroupPermissionDto() - .setUuid(uuidFactory.create()) - .setGroupUuid(group.getUuid()) - .setRole(permission.getKey())); - } - - private void addCurrentUserToGroup(DbSession dbSession, GroupDto group, String createUserUuid) { - dbClient.userGroupDao().insert( - dbSession, - new UserGroupDto().setGroupUuid(group.getUuid()).setUserUuid(createUserUuid)); - } -} diff --git a/server/sonar-webserver-auth/src/main/java/org/sonar/server/organization/OrganizationValidation.java b/server/sonar-webserver-auth/src/main/java/org/sonar/server/organization/OrganizationValidation.java deleted file mode 100644 index 7b625e8a445..00000000000 --- a/server/sonar-webserver-auth/src/main/java/org/sonar/server/organization/OrganizationValidation.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2020 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.organization; - -import javax.annotation.CheckForNull; -import javax.annotation.Nullable; - -public interface OrganizationValidation { - int KEY_MIN_LENGTH = 1; - int KEY_MAX_LENGTH = 255; - int NAME_MIN_LENGTH = 1; - int NAME_MAX_LENGTH = 255; - int DESCRIPTION_MAX_LENGTH = 256; - int URL_MAX_LENGTH = 256; - - /** - * Ensures the specified argument is a valid key by failing with an exception if it is not so. - *

- * A valid key is non null and its length is between {@link #KEY_MIN_LENGTH} and {@link #KEY_MAX_LENGTH}. - *

- * - * @return the argument - * - * @throws NullPointerException if argument is {@code null}. - * @throws IllegalArgumentException if argument is not a valid key. - */ - String checkKey(String keyCandidate); - - /** - * Ensures the specified argument is a valid name by failing with an exception if it is not so. - *

- * A valid name is non null and its length is between {@link #NAME_MIN_LENGTH} and {@link #NAME_MAX_LENGTH}. - *

- * - * @return the argument - * - * @throws NullPointerException if argument is {@code null}. - * @throws IllegalArgumentException if argument is not a valid name. - */ - String checkName(String nameCandidate); - - /** - * Ensures the specified argument is either {@code null}, empty or a valid description by failing with an exception - * if it is not so. - *

- * The length of a valid url can't be more than {@link #DESCRIPTION_MAX_LENGTH 256}. - *

- * - * @return the argument - * - * @throws IllegalArgumentException if argument is not a valid description. - */ - @CheckForNull - String checkDescription(@Nullable String descriptionCandidate); - - /** - * Ensures the specified argument is either {@code null}, empty or a valid URL by failing with an exception if it is - * not so. - *

- * The length of a valid URL can't be more than {@link #URL_MAX_LENGTH 256}. - *

- * - * @return the argument - * - * @throws IllegalArgumentException if argument is not a valid url. - */ - @CheckForNull - String checkUrl(@Nullable String urlCandidate); - - /** - * Ensures the specified argument is either {@code null}, empty or a valid avatar URL by failing with an exception if - * it is not so. - *

- * The length of a valid avatar URL can't be more than {@link #URL_MAX_LENGTH 256}. - *

- * - * @return the argument - * - * @throws IllegalArgumentException if argument is not a valid avatar url. - */ - @CheckForNull - String checkAvatar(@Nullable String avatarCandidate); - - /** - * Transforms the specified string into a valid key. - * - * @see #checkKey(String) - */ - String generateKeyFrom(String source); -} diff --git a/server/sonar-webserver-auth/src/main/java/org/sonar/server/organization/OrganizationValidationImpl.java b/server/sonar-webserver-auth/src/main/java/org/sonar/server/organization/OrganizationValidationImpl.java deleted file mode 100644 index af86a99fc26..00000000000 --- a/server/sonar-webserver-auth/src/main/java/org/sonar/server/organization/OrganizationValidationImpl.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2020 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.organization; - -import javax.annotation.CheckForNull; -import javax.annotation.Nullable; - -import static com.google.common.base.Preconditions.checkArgument; -import static java.util.Objects.requireNonNull; -import static org.sonar.core.util.Slug.slugify; - -public class OrganizationValidationImpl implements OrganizationValidation { - - @Override - public String checkKey(String keyCandidate) { - requireNonNull(keyCandidate, "key can't be null"); - checkArgument(keyCandidate.length() >= KEY_MIN_LENGTH, "Key must not be empty"); - checkArgument(keyCandidate.length() <= KEY_MAX_LENGTH, "Key '%s' must be at most %s chars long", keyCandidate, KEY_MAX_LENGTH); - checkArgument(slugify(keyCandidate).equals(keyCandidate), "Key '%s' contains at least one invalid char", keyCandidate); - - return keyCandidate; - } - - @Override - public String checkName(String nameCandidate) { - requireNonNull(nameCandidate, "name can't be null"); - - checkArgument(nameCandidate.length() >= NAME_MIN_LENGTH, "Name must not be empty"); - checkArgument(nameCandidate.length() <= NAME_MAX_LENGTH, "Name '%s' must be at most %s chars long", nameCandidate, NAME_MAX_LENGTH); - - return nameCandidate; - } - - @Override - public String checkDescription(@Nullable String descriptionCandidate) { - checkParamMaxLength(descriptionCandidate, "Description", DESCRIPTION_MAX_LENGTH); - - return descriptionCandidate; - } - - @Override - public String checkUrl(@Nullable String urlCandidate) { - checkParamMaxLength(urlCandidate, "Url", URL_MAX_LENGTH); - - return urlCandidate; - } - - @Override - public String checkAvatar(@Nullable String avatarCandidate) { - checkParamMaxLength(avatarCandidate, "Avatar", URL_MAX_LENGTH); - - return avatarCandidate; - } - - @CheckForNull - private static void checkParamMaxLength(@Nullable String value, String label, int maxLength) { - if (value != null) { - checkArgument(value.length() <= maxLength, "%s '%s' must be at most %s chars long", label, value, maxLength); - } - } - - @Override - public String generateKeyFrom(String source) { - return slugify(source); - } -} diff --git a/server/sonar-webserver-auth/src/test/java/org/sonar/server/organization/OrganizationUpdaterImplTest.java b/server/sonar-webserver-auth/src/test/java/org/sonar/server/organization/OrganizationUpdaterImplTest.java deleted file mode 100644 index 31db257bfc2..00000000000 --- a/server/sonar-webserver-auth/src/test/java/org/sonar/server/organization/OrganizationUpdaterImplTest.java +++ /dev/null @@ -1,336 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2020 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.organization; - -import java.util.List; -import java.util.Optional; -import java.util.function.Consumer; -import org.apache.commons.lang.RandomStringUtils; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.sonar.api.impl.utils.TestSystem2; -import org.sonar.api.resources.Qualifiers; -import org.sonar.api.resources.ResourceTypes; -import org.sonar.api.utils.System2; -import org.sonar.core.util.SequenceUuidFactory; -import org.sonar.core.util.UuidFactory; -import org.sonar.db.DbClient; -import org.sonar.db.DbSession; -import org.sonar.db.DbTester; -import org.sonar.db.component.ResourceTypesRule; -import org.sonar.db.organization.OrganizationDto; -import org.sonar.db.organization.OrganizationDto.Subscription; -import org.sonar.db.qualitygate.QualityGateDto; -import org.sonar.db.qualityprofile.QProfileDto; -import org.sonar.db.qualityprofile.RulesProfileDto; -import org.sonar.db.user.GroupDto; -import org.sonar.db.user.UserDto; -import org.sonar.db.user.UserMembershipDto; -import org.sonar.db.user.UserMembershipQuery; -import org.sonar.server.es.EsTester; -import org.sonar.server.es.SearchOptions; -import org.sonar.server.permission.PermissionService; -import org.sonar.server.permission.PermissionServiceImpl; -import org.sonar.server.qualityprofile.BuiltInQProfile; -import org.sonar.server.qualityprofile.BuiltInQProfileRepositoryRule; -import org.sonar.server.qualityprofile.QProfileName; -import org.sonar.server.user.index.UserIndex; -import org.sonar.server.user.index.UserIndexer; -import org.sonar.server.user.index.UserQuery; -import org.sonar.server.usergroups.DefaultGroupCreator; -import org.sonar.server.usergroups.DefaultGroupCreatorImpl; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.fail; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.sonar.server.language.LanguageTesting.newLanguage; -import static org.sonar.server.organization.OrganizationUpdater.NewOrganization.newOrganizationBuilder; - -public class OrganizationUpdaterImplTest { - private static final long A_DATE = 12893434L; - - private final OrganizationUpdater.NewOrganization FULL_POPULATED_NEW_ORGANIZATION = newOrganizationBuilder() - .setName("a-name") - .setKey("a-key") - .setDescription("a-description") - .setUrl("a-url") - .setAvatarUrl("a-avatar") - .build(); - - private final System2 system2 = new TestSystem2().setNow(A_DATE); - - private static final Consumer EMPTY_ORGANIZATION_CONSUMER = o -> { - }; - - @Rule - public DbTester db = DbTester.create(system2); - @Rule - public EsTester es = EsTester.create(); - @Rule - public ExpectedException expectedException = ExpectedException.none(); - @Rule - public BuiltInQProfileRepositoryRule builtInQProfileRepositoryRule = new BuiltInQProfileRepositoryRule(); - - private final DbSession dbSession = db.getSession(); - - private final IllegalArgumentException exceptionThrownByOrganizationValidation = new IllegalArgumentException("simulate IAE thrown by OrganizationValidation"); - private final DbClient dbClient = db.getDbClient(); - private final UuidFactory uuidFactory = new SequenceUuidFactory(); - private final OrganizationValidation organizationValidation = mock(OrganizationValidation.class); - private final UserIndexer userIndexer = new UserIndexer(dbClient, es.client()); - private final UserIndex userIndex = new UserIndex(es.client(), system2); - private final DefaultGroupCreator defaultGroupCreator = new DefaultGroupCreatorImpl(dbClient, uuidFactory, TestDefaultOrganizationProvider.from(db)); - - private final ResourceTypes resourceTypes = new ResourceTypesRule().setRootQualifiers(Qualifiers.PROJECT); - private final PermissionService permissionService = new PermissionServiceImpl(resourceTypes); - - private final OrganizationUpdaterImpl underTest = new OrganizationUpdaterImpl(dbClient, system2, uuidFactory, organizationValidation, userIndexer, - builtInQProfileRepositoryRule, defaultGroupCreator, permissionService); - - @Test - public void create_creates_organization_with_properties_from_NewOrganization_arg() throws OrganizationUpdater.KeyConflictException { - builtInQProfileRepositoryRule.initialize(); - UserDto user = db.users().insertUser(); - db.qualityGates().insertBuiltInQualityGate(); - - underTest.create(dbSession, user, FULL_POPULATED_NEW_ORGANIZATION, EMPTY_ORGANIZATION_CONSUMER); - - OrganizationDto organization = dbClient.organizationDao().selectByKey(dbSession, FULL_POPULATED_NEW_ORGANIZATION.getKey()).get(); - assertThat(organization.getUuid()).isNotEmpty(); - assertThat(organization.getKey()).isEqualTo(FULL_POPULATED_NEW_ORGANIZATION.getKey()); - assertThat(organization.getName()).isEqualTo(FULL_POPULATED_NEW_ORGANIZATION.getName()); - assertThat(organization.getDescription()).isEqualTo(FULL_POPULATED_NEW_ORGANIZATION.getDescription()); - assertThat(organization.getUrl()).isEqualTo(FULL_POPULATED_NEW_ORGANIZATION.getUrl()); - assertThat(organization.getAvatarUrl()).isEqualTo(FULL_POPULATED_NEW_ORGANIZATION.getAvatar()); - assertThat(organization.getSubscription()).isEqualTo(Subscription.FREE); - assertThat(organization.getCreatedAt()).isEqualTo(A_DATE); - assertThat(organization.getUpdatedAt()).isEqualTo(A_DATE); - } - - @Test - public void create_creates_members_group_and_add_current_user_to_it() throws OrganizationUpdater.KeyConflictException { - UserDto user = db.users().insertUser(); - builtInQProfileRepositoryRule.initialize(); - db.qualityGates().insertBuiltInQualityGate(); - - underTest.create(dbSession, user, FULL_POPULATED_NEW_ORGANIZATION, EMPTY_ORGANIZATION_CONSUMER); - - verifyMembersGroup(user); - } - - @Test - public void create_does_not_require_description_url_and_avatar_to_be_non_null() throws OrganizationUpdater.KeyConflictException { - builtInQProfileRepositoryRule.initialize(); - UserDto user = db.users().insertUser(); - db.qualityGates().insertBuiltInQualityGate(); - - underTest.create(dbSession, user, newOrganizationBuilder() - .setKey("key") - .setName("name") - .build(), EMPTY_ORGANIZATION_CONSUMER); - - OrganizationDto organization = dbClient.organizationDao().selectByKey(dbSession, "key").get(); - assertThat(organization.getKey()).isEqualTo("key"); - assertThat(organization.getName()).isEqualTo("name"); - assertThat(organization.getDescription()).isNull(); - assertThat(organization.getUrl()).isNull(); - assertThat(organization.getAvatarUrl()).isNull(); - } - - // TODO this test should be removed when default organization entry is removed from db. For now regardless of which org we provide, the test - // makes sure the user is assigned to default org - @Test - public void create_add_current_user_as_member_of_default_organization() throws OrganizationUpdater.KeyConflictException { - UserDto user = db.users().insertUser(); - builtInQProfileRepositoryRule.initialize(); - db.qualityGates().insertBuiltInQualityGate(); - - underTest.create(dbSession, user, FULL_POPULATED_NEW_ORGANIZATION, EMPTY_ORGANIZATION_CONSUMER); - - assertThat( - userIndex.search(UserQuery.builder().setOrganizationUuid(db.getDefaultOrganization().getUuid()).setTextQuery(user.getLogin()).build(), new SearchOptions()).getTotal()) - .isEqualTo(1L); - } - - @Test - public void create_associates_to_built_in_quality_profiles() throws OrganizationUpdater.KeyConflictException { - BuiltInQProfile builtIn1 = builtInQProfileRepositoryRule.add(newLanguage("foo"), "qp1", true); - BuiltInQProfile builtIn2 = builtInQProfileRepositoryRule.add(newLanguage("foo"), "qp2"); - builtInQProfileRepositoryRule.initialize(); - insertRulesProfile(builtIn1); - insertRulesProfile(builtIn2); - UserDto user = db.users().insertUser(); - db.qualityGates().insertBuiltInQualityGate(); - - underTest.create(dbSession, user, FULL_POPULATED_NEW_ORGANIZATION, EMPTY_ORGANIZATION_CONSUMER); - - List profiles = dbClient.qualityProfileDao().selectAll(dbSession); - assertThat(profiles).extracting(p -> new QProfileName(p.getLanguage(), p.getName())).containsExactlyInAnyOrder( - builtIn1.getQProfileName(), builtIn2.getQProfileName()); - assertThat(dbClient.qualityProfileDao().selectDefaultProfile(dbSession, "foo").getName()) - .isEqualTo("qp1"); - } - - private void insertRulesProfile(BuiltInQProfile builtIn) { - RulesProfileDto dto = new RulesProfileDto() - .setIsBuiltIn(true) - .setUuid(RandomStringUtils.randomAlphabetic(40)) - .setLanguage(builtIn.getLanguage()) - .setName(builtIn.getName()); - dbClient.qualityProfileDao().insert(db.getSession(), dto); - db.commit(); - } - - @Test - public void create_calls_consumer() throws OrganizationUpdater.KeyConflictException { - UserDto user = db.users().insertUser(); - builtInQProfileRepositoryRule.initialize(); - db.qualityGates().insertBuiltInQualityGate(); - Boolean[] isConsumerCalled = new Boolean[] {false}; - - underTest.create(dbSession, user, FULL_POPULATED_NEW_ORGANIZATION, o -> { - isConsumerCalled[0] = true; - }); - - assertThat(isConsumerCalled[0]).isEqualTo(true); - } - - @Test - public void create_throws_NPE_if_NewOrganization_arg_is_null() throws OrganizationUpdater.KeyConflictException { - UserDto user = db.users().insertUser(); - - expectedException.expect(NullPointerException.class); - expectedException.expectMessage("newOrganization can't be null"); - - underTest.create(dbSession, user, null, EMPTY_ORGANIZATION_CONSUMER); - } - - @Test - public void create_throws_exception_thrown_by_checkValidKey() throws OrganizationUpdater.KeyConflictException { - UserDto user = db.users().insertUser(); - - when(organizationValidation.checkKey(FULL_POPULATED_NEW_ORGANIZATION.getKey())) - .thenThrow(exceptionThrownByOrganizationValidation); - - createThrowsExceptionThrownByOrganizationValidation(user); - } - - @Test - public void create_throws_exception_thrown_by_checkValidDescription() throws OrganizationUpdater.KeyConflictException { - UserDto user = db.users().insertUser(); - - when(organizationValidation.checkDescription(FULL_POPULATED_NEW_ORGANIZATION.getDescription())).thenThrow(exceptionThrownByOrganizationValidation); - - createThrowsExceptionThrownByOrganizationValidation(user); - } - - @Test - public void create_throws_exception_thrown_by_checkValidUrl() throws OrganizationUpdater.KeyConflictException { - UserDto user = db.users().insertUser(); - - when(organizationValidation.checkUrl(FULL_POPULATED_NEW_ORGANIZATION.getUrl())).thenThrow(exceptionThrownByOrganizationValidation); - - createThrowsExceptionThrownByOrganizationValidation(user); - } - - @Test - public void create_throws_exception_thrown_by_checkValidAvatar() throws OrganizationUpdater.KeyConflictException { - UserDto user = db.users().insertUser(); - - when(organizationValidation.checkAvatar(FULL_POPULATED_NEW_ORGANIZATION.getAvatar())).thenThrow(exceptionThrownByOrganizationValidation); - - createThrowsExceptionThrownByOrganizationValidation(user); - } - - private void createThrowsExceptionThrownByOrganizationValidation(UserDto user) throws OrganizationUpdater.KeyConflictException { - try { - underTest.create(dbSession, user, FULL_POPULATED_NEW_ORGANIZATION, EMPTY_ORGANIZATION_CONSUMER); - fail(exceptionThrownByOrganizationValidation + " should have been thrown"); - } catch (IllegalArgumentException e) { - assertThat(e).isSameAs(exceptionThrownByOrganizationValidation); - } - } - - @Test - public void create_fails_with_KeyConflictException_if_org_with_key_in_NewOrganization_arg_already_exists_in_db() throws OrganizationUpdater.KeyConflictException { - db.organizations().insertForKey(FULL_POPULATED_NEW_ORGANIZATION.getKey()); - UserDto user = db.users().insertUser(); - - expectedException.expect(OrganizationUpdater.KeyConflictException.class); - expectedException.expectMessage("Organization key '" + FULL_POPULATED_NEW_ORGANIZATION.getKey() + "' is already used"); - - underTest.create(dbSession, user, FULL_POPULATED_NEW_ORGANIZATION, EMPTY_ORGANIZATION_CONSUMER); - } - - @Test - public void update_personal_organization() { - OrganizationDto organization = db.organizations().insert(o -> o.setKey("old login")); - when(organizationValidation.generateKeyFrom("new_login")).thenReturn("new_login"); - - underTest.updateOrganizationKey(dbSession, organization, "new_login"); - - OrganizationDto organizationReloaded = dbClient.organizationDao().selectByUuid(dbSession, organization.getUuid()).get(); - assertThat(organizationReloaded.getKey()).isEqualTo("new_login"); - } - - @Test - public void does_not_update_personal_organization_when_generated_organization_key_does_not_change() { - OrganizationDto organization = db.organizations().insert(o -> o.setKey("login")); - when(organizationValidation.generateKeyFrom("Login")).thenReturn("login"); - - underTest.updateOrganizationKey(dbSession, organization, "Login"); - - OrganizationDto organizationReloaded = dbClient.organizationDao().selectByUuid(dbSession, organization.getUuid()).get(); - assertThat(organizationReloaded.getKey()).isEqualTo("login"); - } - - @Test - public void fail_to_update_personal_organization_when_new_key_already_exist() { - OrganizationDto organization = db.organizations().insert(); - db.organizations().insert(o -> o.setKey("new_login")); - when(organizationValidation.generateKeyFrom("new_login")).thenReturn("new_login"); - - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage("Can't create organization with key 'new_login' because an organization with this key already exists"); - - underTest.updateOrganizationKey(dbSession, organization, "new_login"); - } - - private void verifyMembersGroup(UserDto user) { - Optional groupOpt = dbClient.groupDao().selectByName(dbSession, "Members"); - assertThat(groupOpt).isPresent(); - GroupDto groupDto = groupOpt.get(); - assertThat(groupDto.getDescription()).isEqualTo("All members of the organization"); - - assertThat(dbClient.groupPermissionDao().selectGlobalPermissionsOfGroup(dbSession, groupDto.getUuid())).isEmpty(); - List members = dbClient.groupMembershipDao().selectMembers( - dbSession, - UserMembershipQuery.builder() - .groupUuid(groupDto.getUuid()) - .membership(UserMembershipQuery.IN).build(), - 0, Integer.MAX_VALUE); - assertThat(members) - .extracting(UserMembershipDto::getLogin) - .containsOnly(user.getLogin()); - } - -} diff --git a/server/sonar-webserver-auth/src/test/java/org/sonar/server/organization/OrganizationValidationImplTest.java b/server/sonar-webserver-auth/src/test/java/org/sonar/server/organization/OrganizationValidationImplTest.java deleted file mode 100644 index e585d5c7b62..00000000000 --- a/server/sonar-webserver-auth/src/test/java/org/sonar/server/organization/OrganizationValidationImplTest.java +++ /dev/null @@ -1,240 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2020 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.organization; - -import com.google.common.base.Strings; -import java.util.Random; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.fail; - -public class OrganizationValidationImplTest { - private static final String STRING_32_CHARS = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; - private static final String STRING_64_CHARS = STRING_32_CHARS + STRING_32_CHARS; - private static final String STRING_256_CHARS = STRING_64_CHARS + STRING_64_CHARS + STRING_64_CHARS + STRING_64_CHARS; - - private static final String STRING_255_CHARS = Strings.repeat("a", 255); - - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - private OrganizationValidationImpl underTest = new OrganizationValidationImpl(); - - @Test - public void checkValidKey_throws_NPE_if_arg_is_null() { - expectedException.expect(NullPointerException.class); - expectedException.expectMessage("key can't be null"); - - underTest.checkKey(null); - } - - @Test - public void checkValidKey_throws_IAE_if_arg_is_empty() { - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage("Key must not be empty"); - - underTest.checkKey(""); - } - - @Test - public void checkValidKey_throws_IAE_if_key_is_empty() { - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage("Key must not be empty"); - - underTest.checkKey(""); - } - - @Test - public void checkValidKey_does_not_fail_if_arg_is_1_to_255_chars_long() { - String str = "a"; - for (int i = 0; i < 254; i++) { - underTest.checkKey(str); - str += "a"; - } - } - - @Test - public void checkValidKey_throws_IAE_when_more_than_300_characters() { - String key = STRING_255_CHARS + "b"; - - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage("Key '" + key + "' must be at most 255 chars long"); - - underTest.checkKey(key); - } - - @Test - public void checkValidKey_throws_IAE_if_arg_contains_invalid_chars() { - char[] invalidChars = {'é', '<', '@'}; - - for (char invalidChar : invalidChars) { - String str = "aa" + invalidChar; - try { - underTest.checkKey(str); - fail("A IllegalArgumentException should have been thrown"); - } catch (IllegalArgumentException e) { - assertThat(e).hasMessage("Key '" + str + "' contains at least one invalid char"); - } - } - } - - @Test - public void checkValidName_throws_NPE_if_arg_is_null() { - expectedException.expect(NullPointerException.class); - expectedException.expectMessage("name can't be null"); - - underTest.checkName(null); - } - - @Test - public void checkValidName_throws_IAE_if_empty() { - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage("Name must not be empty"); - - underTest.checkName(""); - } - - @Test - public void checkValidName_does_not_fail_if_arg_is_1_to_255_chars_long() { - String str = "a"; - for (int i = 0; i < 254; i++) { - underTest.checkName(str); - str += "a"; - } - } - - @Test - public void checkValidName_throws_IAE_when_more_than_255_characters() { - String str = STRING_255_CHARS + "b"; - - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage("Name '" + str + "' must be at most 255 chars long"); - - underTest.checkName(str); - } - - @Test - public void checkValidDescription_does_not_fail_if_arg_is_null() { - underTest.checkDescription(null); - } - - @Test - public void checkValidDescription_does_not_fail_if_arg_is_empty() { - underTest.checkDescription(""); - } - - @Test - public void checkValidDescription_does_not_fail_if_arg_is_1_to_256_chars_long() { - String str = "1"; - for (int i = 0; i < 256; i++) { - underTest.checkDescription(str); - str += "a"; - } - } - - @Test - public void checkValidDescription_throws_IAE_if_arg_is_more_than_256_chars_long() { - String str = STRING_256_CHARS; - underTest.checkDescription(str); - for (int i = 0; i < 5 + Math.abs(new Random().nextInt(10)); i++) { - str += "c"; - try { - underTest.checkDescription(str); - fail("A IllegalArgumentException should have been thrown"); - } catch (IllegalArgumentException e) { - assertThat(e).hasMessage("Description '" + str + "' must be at most 256 chars long"); - } - } - } - - @Test - public void checkValidUrl_does_not_fail_if_arg_is_null() { - underTest.checkUrl(null); - } - - @Test - public void checkValidUrl_does_not_fail_if_arg_is_1_to_256_chars_long() { - String str = "1"; - for (int i = 0; i < 256; i++) { - underTest.checkUrl(str); - str += "a"; - } - } - - @Test - public void checkValidUrl_throws_IAE_if_arg_is_more_than_256_chars_long() { - String str = STRING_256_CHARS; - underTest.checkUrl(str); - for (int i = 0; i < 5 + Math.abs(new Random().nextInt(10)); i++) { - str += "c"; - try { - underTest.checkUrl(str); - fail("A IllegalArgumentException should have been thrown"); - } catch (IllegalArgumentException e) { - assertThat(e).hasMessage("Url '" + str + "' must be at most 256 chars long"); - } - } - } - - @Test - public void checkValidAvatar_does_not_fail_if_arg_is_null() { - underTest.checkAvatar(null); - } - - @Test - public void checkValidAvatar_does_not_fail_if_arg_is_1_to_256_chars_long() { - String str = "1"; - for (int i = 0; i < 256; i++) { - underTest.checkAvatar(str); - str += "a"; - } - } - - @Test - public void checkValidAvatar_throws_IAE_if_arg_is_more_than_256_chars_long() { - String str = STRING_256_CHARS; - underTest.checkAvatar(str); - for (int i = 0; i < 5 + Math.abs(new Random().nextInt(10)); i++) { - str += "c"; - try { - underTest.checkAvatar(str); - fail("A IllegalArgumentException should have been thrown"); - } catch (IllegalArgumentException e) { - assertThat(e).hasMessage("Avatar '" + str + "' must be at most 256 chars long"); - } - } - } - - @Test - public void generateKeyFrom_returns_slug_of_arg() { - assertThat(underTest.generateKeyFrom("foo")).isEqualTo("foo"); - assertThat(underTest.generateKeyFrom(" FOO ")).isEqualTo("foo"); - assertThat(underTest.generateKeyFrom("he's here")).isEqualTo("he-s-here"); - assertThat(underTest.generateKeyFrom("foo-bar")).isEqualTo("foo-bar"); - assertThat(underTest.generateKeyFrom("foo_bar")).isEqualTo("foo_bar"); - assertThat(underTest.generateKeyFrom("accents éà")).isEqualTo("accents-ea"); - assertThat(underTest.generateKeyFrom("")).isEqualTo("foo"); - assertThat(underTest.generateKeyFrom("<\"foo:\">")).isEqualTo("foo"); - } - -} diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/organization/ws/OrganizationsWsModule.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/organization/ws/OrganizationsWsModule.java index 4a9a0526467..bc18f777b36 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/organization/ws/OrganizationsWsModule.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/organization/ws/OrganizationsWsModule.java @@ -32,7 +32,6 @@ public class OrganizationsWsModule extends Module { protected void configureModule() { add( OrganizationsWs.class, - OrganizationsWsSupport.class, MemberUpdater.class, // actions SearchAction.class, diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/organization/ws/OrganizationsWsSupport.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/organization/ws/OrganizationsWsSupport.java deleted file mode 100644 index c9f078838a3..00000000000 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/organization/ws/OrganizationsWsSupport.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2020 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.organization.ws; - -import javax.annotation.CheckForNull; -import org.sonar.api.server.ws.Request; -import org.sonar.api.server.ws.WebService; -import org.sonar.db.DbClient; -import org.sonar.db.DbSession; -import org.sonar.db.organization.OrganizationDto; -import org.sonar.server.organization.OrganizationValidation; -import org.sonarqube.ws.Organizations.Organization; - -import static com.google.common.base.Preconditions.checkArgument; -import static java.util.Optional.ofNullable; -import static org.sonar.server.organization.OrganizationValidation.DESCRIPTION_MAX_LENGTH; -import static org.sonar.server.organization.OrganizationValidation.NAME_MAX_LENGTH; -import static org.sonar.server.organization.OrganizationValidation.NAME_MIN_LENGTH; -import static org.sonar.server.organization.OrganizationValidation.URL_MAX_LENGTH; - -/** - * Factorizes code and constants between Organization WS's actions. - */ -public class OrganizationsWsSupport { - static final String PARAM_ORGANIZATION = "organization"; - static final String PARAM_KEY = "key"; - static final String PARAM_NAME = "name"; - static final String PARAM_DESCRIPTION = "description"; - static final String PARAM_URL = "url"; - static final String PARAM_AVATAR_URL = "avatar"; - static final String PARAM_LOGIN = "login"; - - private final OrganizationValidation organizationValidation; - private final DbClient dbClient; - - public OrganizationsWsSupport(OrganizationValidation organizationValidation, DbClient dbClient) { - this.organizationValidation = organizationValidation; - this.dbClient = dbClient; - } - - String getAndCheckMandatoryName(Request request) { - String name = request.mandatoryParam(PARAM_NAME); - organizationValidation.checkName(name); - return name; - } - - @CheckForNull - String getAndCheckName(Request request) { - String name = request.param(PARAM_NAME); - if (name != null) { - organizationValidation.checkName(name); - } - return name; - } - - @CheckForNull - String getAndCheckAvatar(Request request) { - return organizationValidation.checkAvatar(request.param(PARAM_AVATAR_URL)); - } - - @CheckForNull - String getAndCheckUrl(Request request) { - return organizationValidation.checkUrl(request.param(PARAM_URL)); - } - - @CheckForNull - String getAndCheckDescription(Request request) { - return organizationValidation.checkDescription(request.param(PARAM_DESCRIPTION)); - } - - void addOrganizationDetailsParams(WebService.NewAction action, boolean isNameRequired) { - action.createParam(PARAM_NAME) - .setRequired(isNameRequired) - .setMinimumLength(NAME_MIN_LENGTH) - .setMaximumLength(NAME_MAX_LENGTH) - .setDescription("Name of the organization") - .setExampleValue("Foo Company"); - - action.createParam(PARAM_DESCRIPTION) - .setRequired(false) - .setMaximumLength(DESCRIPTION_MAX_LENGTH) - .setDescription("Description of the organization.
It must be less than 256 chars long.") - .setExampleValue("The Foo company produces quality software for Bar."); - - action.createParam(PARAM_URL) - .setRequired(false) - .setMaximumLength(URL_MAX_LENGTH) - .setDescription("URL of the organization.
It must be less than 256 chars long.") - .setExampleValue("https://www.foo.com"); - - action.createParam(PARAM_AVATAR_URL) - .setRequired(false) - .setMaximumLength(URL_MAX_LENGTH) - .setDescription("URL of the organization avatar.
It must be less than 256 chars long.") - .setExampleValue("https://www.foo.com/foo.png"); - } - - Organization.Builder toOrganization(OrganizationDto dto) { - Organization.Builder builder = Organization.newBuilder(); - builder - .setName(dto.getName()) - .setKey(dto.getKey()); - ofNullable(dto.getDescription()).ifPresent(builder::setDescription); - ofNullable(dto.getUrl()).ifPresent(builder::setUrl); - ofNullable(dto.getAvatarUrl()).ifPresent(builder::setAvatar); - return builder; - } - - - void checkMemberSyncIsDisabled(DbSession dbSession, OrganizationDto organization) { - dbClient.organizationAlmBindingDao().selectByOrganization(dbSession, organization).ifPresent(orgAlmBindingDto -> - checkArgument(!orgAlmBindingDto.isMembersSyncEnable(), "You can't add or remove members when synchronization of organization with alm is enabled.")); - } -} diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/organization/ws/SearchMembersAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/organization/ws/SearchMembersAction.java index 8f102fdd5a6..003e9663d31 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/organization/ws/SearchMembersAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/organization/ws/SearchMembersAction.java @@ -54,10 +54,10 @@ import static org.sonar.api.server.ws.WebService.SelectionMode.SELECTED; import static org.sonar.db.permission.GlobalPermission.ADMINISTER; import static org.sonar.server.es.SearchOptions.MAX_PAGE_SIZE; import static org.sonar.server.exceptions.NotFoundException.checkFoundWithOptional; -import static org.sonar.server.organization.ws.OrganizationsWsSupport.PARAM_ORGANIZATION; import static org.sonar.server.ws.WsUtils.writeProtobuf; public class SearchMembersAction implements OrganizationsWsAction { + private static final String ORGANIZATION_PARAM = "organization"; private final DbClient dbClient; private final UserIndex userIndex; @@ -94,7 +94,7 @@ public class SearchMembersAction implements OrganizationsWsAction { .setDefaultValue(SELECTED.value()) .setPossibleValues(SELECTED.value(), SelectionMode.DESELECTED.value()); - action.createParam(PARAM_ORGANIZATION) + action.createParam(ORGANIZATION_PARAM) .setDescription("Organization key") .setInternal(true) .setRequired(false); diff --git a/server/sonar-webserver/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java b/server/sonar-webserver/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java index 42859630994..840894be841 100644 --- a/server/sonar-webserver/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java +++ b/server/sonar-webserver/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java @@ -111,8 +111,6 @@ import org.sonar.server.newcodeperiod.ws.NewCodePeriodsWsModule; import org.sonar.server.notification.NotificationModule; import org.sonar.server.notification.ws.NotificationWsModule; import org.sonar.server.organization.BillingValidationsProxyImpl; -import org.sonar.server.organization.OrganizationUpdaterImpl; -import org.sonar.server.organization.OrganizationValidationImpl; import org.sonar.server.organization.ws.OrganizationsWsModule; import org.sonar.server.permission.DefaultTemplatesResolverImpl; import org.sonar.server.permission.GroupPermissionChanger; @@ -268,8 +266,6 @@ public class PlatformLevel4 extends PlatformLevel { UpdateCenterWsModule.class, // organizations - OrganizationValidationImpl.class, - OrganizationUpdaterImpl.class, OrganizationsWsModule.class, BillingValidationsProxyImpl.class, -- 2.39.5