From f5a9eedb6aded3cc5cbf514419cf23c6e2165373 Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Tue, 25 Sep 2018 08:40:14 +0200 Subject: [PATCH] SONAR-11302 Increase size of organization's key and name As login can be automatically generated from name, size of the personal organization key might be higher than current value (32) --- .../org/sonar/db/version/schema-h2.ddl | 4 +- .../db/organization/OrganizationCount.java | 43 ---------- .../db/organization/OrganizationDto.java | 20 ++++- .../db/migration/version/v74/DbVersion74.java | 1 + ...IncreaseOrganizationsKeeAndNameLength.java | 56 +++++++++++++ .../version/v74/DbVersion74Test.java | 2 +- ...easeOrganizationsKeeAndNameLengthTest.java | 55 +++++++++++++ .../organizations.sql | 20 +++++ .../organization/OrganizationValidation.java | 8 +- .../OrganizationValidationImpl.java | 3 +- .../server/organization/ws/CreateAction.java | 9 ++- .../ws/OrganizationsWsSupport.java | 5 +- .../server/organization/ws/UpdateAction.java | 4 +- .../OrganizationUpdaterImplTest.java | 53 +------------ .../OrganizationValidationImplTest.java | 57 ++++++-------- .../organization/ws/CreateActionTest.java | 78 ++----------------- .../organization/ws/UpdateActionTest.java | 23 +----- 17 files changed, 204 insertions(+), 237 deletions(-) delete mode 100644 server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationCount.java create mode 100644 server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/IncreaseOrganizationsKeeAndNameLength.java create mode 100644 server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/IncreaseOrganizationsKeeAndNameLengthTest.java create mode 100644 server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v74/IncreaseOrganizationsKeeAndNameLengthTest/organizations.sql diff --git a/server/sonar-db-core/src/main/resources/org/sonar/db/version/schema-h2.ddl b/server/sonar-db-core/src/main/resources/org/sonar/db/version/schema-h2.ddl index a792c2be6b1..9ad1de692b4 100644 --- a/server/sonar-db-core/src/main/resources/org/sonar/db/version/schema-h2.ddl +++ b/server/sonar-db-core/src/main/resources/org/sonar/db/version/schema-h2.ddl @@ -1,7 +1,7 @@ CREATE TABLE "ORGANIZATIONS" ( "UUID" VARCHAR(40) NOT NULL, - "KEE" VARCHAR(32) NOT NULL, - "NAME" VARCHAR(64) NOT NULL, + "KEE" VARCHAR(300) NOT NULL, + "NAME" VARCHAR(300) NOT NULL, "DESCRIPTION" VARCHAR(256), "URL" VARCHAR(256), "AVATAR_URL" VARCHAR(256), diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationCount.java b/server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationCount.java deleted file mode 100644 index bd878a28850..00000000000 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationCount.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.organization; - -public class OrganizationCount { - private String organizationUuid; - private int memberCount; - - public String getOrganizationUuid() { - return organizationUuid; - } - - public OrganizationCount setOrganizationUuid(String organizationUuid) { - this.organizationUuid = organizationUuid; - return this; - } - - public int getMemberCount() { - return memberCount; - } - - public OrganizationCount setMemberCount(int memberCount) { - this.memberCount = memberCount; - return this; - } -} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationDto.java index 1cfd7eeda66..3ae32fae970 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationDto.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationDto.java @@ -22,6 +22,7 @@ package org.sonar.db.organization; import java.util.Objects; import javax.annotation.CheckForNull; import javax.annotation.Nullable; +import org.sonar.api.server.authentication.UserIdentity; public class OrganizationDto { @@ -44,10 +45,25 @@ public class OrganizationDto { /** Technical unique identifier, can't be null */ private String uuid; - /** Functional unique identifier, can't be null */ + + /** + * Functional unique identifier, can't be null. + * + * On personal organization (created the first time the user authenticates), the key can have the following format : + * - When {@link UserIdentity#getLogin()} is not null, it's a slug of the login + * - When {@link UserIdentity#getLogin()} is null, it's a slug of the name appended to a random number + * + * Length is set to 300 (As login length is 255, the size must be higher than 255). + */ private String key; - /** Name, can't be null */ + + /** + * Name, can't be null. + * + * Length is set to 300, as it's generated from the key when no name is provided. + */ private String name; + /** description can't be null */ private String description; /** url can be null */ diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/DbVersion74.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/DbVersion74.java index ef613562bd8..0591f0bee2c 100644 --- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/DbVersion74.java +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/DbVersion74.java @@ -41,6 +41,7 @@ public class DbVersion74 implements DbVersion { .add(2318, "Finalize CE_QUEUE.MAIN_COMPONENT_UUID 3/3", FinalizeMainComponentUuidColumnsToCeActivity.class) .add(2319, "Finalize CE_ACTIVITY.MAIN_COMPONENT_UUID 3/3", FinalizeMainComponentUuidColumnsToCeQueue.class) .add(2320, "Finalize CE_ACTIVITY.MAIN_LAST_KEY 3/3", FinalizeMainLastKeyColumnsToCeActivity.class) + .add(2321, "Increase organization key and name length", IncreaseOrganizationsKeeAndNameLength.class) ; } } diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/IncreaseOrganizationsKeeAndNameLength.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/IncreaseOrganizationsKeeAndNameLength.java new file mode 100644 index 00000000000..ca5fa844c06 --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v74/IncreaseOrganizationsKeeAndNameLength.java @@ -0,0 +1,56 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 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.platform.db.migration.version.v74; + +import java.sql.SQLException; +import org.sonar.db.Database; +import org.sonar.server.platform.db.migration.SupportsBlueGreen; +import org.sonar.server.platform.db.migration.sql.AlterColumnsBuilder; +import org.sonar.server.platform.db.migration.step.DdlChange; + +import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.newVarcharColumnDefBuilder; + +@SupportsBlueGreen +public class IncreaseOrganizationsKeeAndNameLength extends DdlChange { + + public static final String ORGANIZATIONS_TABLE = "organizations"; + + public IncreaseOrganizationsKeeAndNameLength(Database db) { + super(db); + } + + @Override + public void execute(Context context) throws SQLException { + context.execute(new AlterColumnsBuilder(getDialect(), ORGANIZATIONS_TABLE) + .updateColumn(newVarcharColumnDefBuilder() + .setColumnName("kee") + .setLimit(300) + .setIsNullable(false) + .build()) + .build()); + context.execute(new AlterColumnsBuilder(getDialect(), ORGANIZATIONS_TABLE) + .updateColumn(newVarcharColumnDefBuilder() + .setColumnName("name") + .setLimit(300) + .setIsNullable(false) + .build()) + .build()); + } +} diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/DbVersion74Test.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/DbVersion74Test.java index 7ba5fae6ba5..824f8b2feb4 100644 --- a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/DbVersion74Test.java +++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/DbVersion74Test.java @@ -35,6 +35,6 @@ public class DbVersion74Test { @Test public void verify_migration_count() { - verifyMigrationCount(underTest, 14); + verifyMigrationCount(underTest, 15); } } diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/IncreaseOrganizationsKeeAndNameLengthTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/IncreaseOrganizationsKeeAndNameLengthTest.java new file mode 100644 index 00000000000..46d2f19ebbd --- /dev/null +++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v74/IncreaseOrganizationsKeeAndNameLengthTest.java @@ -0,0 +1,55 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 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.platform.db.migration.version.v74; + +import java.sql.SQLException; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.db.CoreDbTester; + +import static java.sql.Types.VARCHAR; + +public class IncreaseOrganizationsKeeAndNameLengthTest { + + @Rule + public final CoreDbTester db = CoreDbTester.createForSchema(IncreaseOrganizationsKeeAndNameLengthTest.class, "organizations.sql"); + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private IncreaseOrganizationsKeeAndNameLength underTest = new IncreaseOrganizationsKeeAndNameLength(db.database()); + + @Test + public void column_is_updated() throws SQLException { + underTest.execute(); + + db.assertColumnDefinition("organizations", "kee", VARCHAR, 300, false); + db.assertColumnDefinition("organizations", "name", VARCHAR, 300, false); + } + + @Test + public void migration_is_reentrant() throws SQLException { + underTest.execute(); + + underTest.execute(); + } + +} diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v74/IncreaseOrganizationsKeeAndNameLengthTest/organizations.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v74/IncreaseOrganizationsKeeAndNameLengthTest/organizations.sql new file mode 100644 index 00000000000..4583ca9967b --- /dev/null +++ b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v74/IncreaseOrganizationsKeeAndNameLengthTest/organizations.sql @@ -0,0 +1,20 @@ +CREATE TABLE "ORGANIZATIONS" ( + "UUID" VARCHAR(40) NOT NULL, + "KEE" VARCHAR(32) NOT NULL, + "NAME" VARCHAR(64) NOT NULL, + "DESCRIPTION" VARCHAR(256), + "URL" VARCHAR(256), + "AVATAR_URL" VARCHAR(256), + "GUARDED" BOOLEAN NOT NULL, + "DEFAULT_PERM_TEMPLATE_PROJECT" VARCHAR(40), + "DEFAULT_PERM_TEMPLATE_VIEW" VARCHAR(40), + "DEFAULT_GROUP_ID" INTEGER, + "DEFAULT_QUALITY_GATE_UUID" VARCHAR(40) NOT NULL, + "NEW_PROJECT_PRIVATE" BOOLEAN NOT NULL, + "SUBSCRIPTION" VARCHAR(40) NOT NULL, + "CREATED_AT" BIGINT NOT NULL, + "UPDATED_AT" BIGINT NOT NULL, + + CONSTRAINT "PK_ORGANIZATIONS" PRIMARY KEY ("UUID") +); +CREATE UNIQUE INDEX "ORGANIZATION_KEY" ON "ORGANIZATIONS" ("KEE"); \ No newline at end of file diff --git a/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationValidation.java b/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationValidation.java index ef41e6e3c80..1e5f148e26f 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationValidation.java +++ b/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationValidation.java @@ -24,16 +24,16 @@ import javax.annotation.Nullable; public interface OrganizationValidation { int KEY_MIN_LENGTH = 1; - int KEY_MAX_LENGTH = 32; + int KEY_MAX_LENGTH = 300; int NAME_MIN_LENGTH = 1; - int NAME_MAX_LENGTH = 64; + int NAME_MAX_LENGTH = 300; 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 2} and {@link #KEY_MAX_LENGTH 32}. + * A valid key is non null and its length is between {@link #KEY_MIN_LENGTH} and {@link #KEY_MAX_LENGTH}. *

* * @return the argument @@ -46,7 +46,7 @@ public interface OrganizationValidation { /** * 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 2} and {@link #NAME_MAX_LENGTH 64}. + * A valid name is non null and its length is between {@link #NAME_MIN_LENGTH} and {@link #NAME_MAX_LENGTH}. *

* * @return the argument diff --git a/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationValidationImpl.java b/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationValidationImpl.java index 516dfae762b..59081a5a028 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationValidationImpl.java +++ b/server/sonar-server/src/main/java/org/sonar/server/organization/OrganizationValidationImpl.java @@ -23,7 +23,6 @@ import javax.annotation.CheckForNull; import javax.annotation.Nullable; import static com.google.common.base.Preconditions.checkArgument; -import static java.lang.Math.min; import static java.util.Objects.requireNonNull; import static org.sonar.core.util.Slug.slugify; @@ -79,6 +78,6 @@ public class OrganizationValidationImpl implements OrganizationValidation { @Override public String generateKeyFrom(String source) { - return slugify(source.substring(0, min(source.length(), KEY_MAX_LENGTH))); + return slugify(source); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/organization/ws/CreateAction.java b/server/sonar-server/src/main/java/org/sonar/server/organization/ws/CreateAction.java index 894bb7e10eb..136866aff69 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/organization/ws/CreateAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/organization/ws/CreateAction.java @@ -40,6 +40,7 @@ import org.sonarqube.ws.Organizations.CreateWsResponse; import static com.google.common.base.Preconditions.checkArgument; import static org.sonar.server.organization.OrganizationUpdater.NewOrganization.newOrganizationBuilder; import static org.sonar.server.organization.OrganizationValidation.KEY_MAX_LENGTH; +import static org.sonar.server.organization.OrganizationValidation.KEY_MIN_LENGTH; import static org.sonar.server.organization.ws.OrganizationsWsSupport.PARAM_KEY; import static org.sonar.server.ws.WsUtils.writeProtobuf; @@ -74,16 +75,20 @@ public class CreateAction implements OrganizationsWsAction { .setResponseExample(getClass().getResource("create-example.json")) .setInternal(true) .setSince("6.2") - .setChangelog(new Change("7.2", "Minimal number of character of name and key is one character")) + .setChangelog( + new Change("7.4", "Maximal number of character of name and key is 300 characters"), + new Change("7.2", "Minimal number of character of name and key is one character") + ) .setHandler(this); action.createParam(PARAM_KEY) .setRequired(false) + .setMinimumLength(KEY_MIN_LENGTH) .setMaximumLength(KEY_MAX_LENGTH) .setDescription("Key of the organization.
" + "The key is unique to the whole SonarQube.
" + "When not specified, the key is computed from the name.
" + - "Otherwise, it must be between 1 and 32 chars long. All chars must be lower-case letters (a to z), digits or dash (but dash can neither be trailing nor heading)") + "All chars must be lower-case letters (a to z), digits or dash (but dash can neither be trailing nor heading)") .setExampleValue("foo-company"); wsSupport.addOrganizationDetailsParams(action, true); diff --git a/server/sonar-server/src/main/java/org/sonar/server/organization/ws/OrganizationsWsSupport.java b/server/sonar-server/src/main/java/org/sonar/server/organization/ws/OrganizationsWsSupport.java index 69aaa1723c4..25f59dd801d 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/organization/ws/OrganizationsWsSupport.java +++ b/server/sonar-server/src/main/java/org/sonar/server/organization/ws/OrganizationsWsSupport.java @@ -29,6 +29,7 @@ import org.sonarqube.ws.Organizations.Organization; import static org.sonar.core.util.Protobuf.setNullable; 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; /** @@ -83,9 +84,9 @@ public class OrganizationsWsSupport { 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.
" + - "It must be between 2 and 64 chars longs.") + .setDescription("Name of the organization") .setExampleValue("Foo Company"); action.createParam(PARAM_DESCRIPTION) diff --git a/server/sonar-server/src/main/java/org/sonar/server/organization/ws/UpdateAction.java b/server/sonar-server/src/main/java/org/sonar/server/organization/ws/UpdateAction.java index 1d2334bba3d..2844e70b992 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/organization/ws/UpdateAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/organization/ws/UpdateAction.java @@ -22,6 +22,7 @@ package org.sonar.server.organization.ws; import java.util.Optional; import javax.annotation.CheckForNull; import javax.annotation.Nullable; +import org.sonar.api.server.ws.Change; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService; @@ -34,12 +35,12 @@ import org.sonar.server.user.UserSession; import org.sonarqube.ws.Organizations; import static java.lang.String.format; +import static org.sonar.db.permission.OrganizationPermission.ADMINISTER; import static org.sonar.server.organization.ws.OrganizationsWsSupport.PARAM_AVATAR_URL; import static org.sonar.server.organization.ws.OrganizationsWsSupport.PARAM_DESCRIPTION; import static org.sonar.server.organization.ws.OrganizationsWsSupport.PARAM_KEY; import static org.sonar.server.organization.ws.OrganizationsWsSupport.PARAM_NAME; import static org.sonar.server.organization.ws.OrganizationsWsSupport.PARAM_URL; -import static org.sonar.db.permission.OrganizationPermission.ADMINISTER; import static org.sonar.server.ws.WsUtils.writeProtobuf; public class UpdateAction implements OrganizationsWsAction { @@ -66,6 +67,7 @@ public class UpdateAction implements OrganizationsWsAction { "Require 'Administer System' permission. Organization support must be enabled.") .setInternal(true) .setSince("6.2") + .setChangelog(new Change("7.4", "Maximal number of character of name is 300 characters")) .setHandler(this); action.createParam(PARAM_KEY) diff --git a/server/sonar-server/src/test/java/org/sonar/server/organization/OrganizationUpdaterImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/organization/OrganizationUpdaterImplTest.java index 14035a152be..b33a585b6c3 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/organization/OrganizationUpdaterImplTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/organization/OrganizationUpdaterImplTest.java @@ -73,7 +73,6 @@ public class OrganizationUpdaterImplTest { private static final long A_DATE = 12893434L; private static final String A_LOGIN = "a-login"; 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 OrganizationUpdater.NewOrganization FULL_POPULATED_NEW_ORGANIZATION = newOrganizationBuilder() @@ -191,7 +190,8 @@ public class OrganizationUpdaterImplTest { 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(ownersGroup.getId(), UserRole.SECURITYHOTSPOT_ADMIN), tuple(ownersGroup.getId(), GlobalPermissions.SCAN_EXECUTION), + tuple(ownersGroup.getId(), UserRole.ADMIN), tuple(ownersGroup.getId(), UserRole.ISSUE_ADMIN), tuple(ownersGroup.getId(), UserRole.SECURITYHOTSPOT_ADMIN), + tuple(ownersGroup.getId(), GlobalPermissions.SCAN_EXECUTION), tuple(defaultGroupId, UserRole.USER), tuple(defaultGroupId, UserRole.CODEVIEWER)); } @@ -425,54 +425,6 @@ public class OrganizationUpdaterImplTest { assertThat(dbClient.organizationMemberDao().select(dbSession, organization.getUuid(), user.getId())).isPresent(); } - @Test - public void createForUser_does_not_fail_if_name_is_too_long_for_an_organization_name() { - String nameTooLong = STRING_64_CHARS + "b"; - UserDto user = db.users().insertUser(dto -> dto.setName(nameTooLong).setLogin(A_LOGIN)); - when(organizationValidation.generateKeyFrom(A_LOGIN)).thenReturn(SLUG_OF_A_LOGIN); - enableCreatePersonalOrg(true); - builtInQProfileRepositoryRule.initialize(); - db.qualityGates().insertBuiltInQualityGate(); - - underTest.createForUser(dbSession, user); - - OrganizationDto organization = dbClient.organizationDao().selectByKey(dbSession, SLUG_OF_A_LOGIN).get(); - assertThat(organization.getName()).isEqualTo(STRING_64_CHARS); - assertThat(organization.getDescription()).isEqualTo(nameTooLong + "'s personal organization"); - } - - @Test - public void createForUser_does_not_fail_if_name_is_empty_and_login_is_too_long_for_an_organization_name() { - String login = STRING_64_CHARS + "b"; - UserDto user = db.users().insertUser(dto -> dto.setName("").setLogin(login)); - when(organizationValidation.generateKeyFrom(login)).thenReturn(SLUG_OF_A_LOGIN); - enableCreatePersonalOrg(true); - builtInQProfileRepositoryRule.initialize(); - db.qualityGates().insertBuiltInQualityGate(); - - underTest.createForUser(dbSession, user); - - OrganizationDto organization = dbClient.organizationDao().selectByKey(dbSession, SLUG_OF_A_LOGIN).get(); - assertThat(organization.getName()).isEqualTo(STRING_64_CHARS); - assertThat(organization.getDescription()).isEqualTo(login + "'s personal organization"); - } - - @Test - public void createForUser_does_not_fail_if_name_is_null_and_login_is_too_long_for_an_organization_name() { - String login = STRING_64_CHARS + "b"; - UserDto user = db.users().insertUser(dto -> dto.setName(null).setLogin(login)); - when(organizationValidation.generateKeyFrom(login)).thenReturn(SLUG_OF_A_LOGIN); - enableCreatePersonalOrg(true); - builtInQProfileRepositoryRule.initialize(); - db.qualityGates().insertBuiltInQualityGate(); - - underTest.createForUser(dbSession, user); - - OrganizationDto organization = dbClient.organizationDao().selectByKey(dbSession, SLUG_OF_A_LOGIN).get(); - assertThat(organization.getName()).isEqualTo(STRING_64_CHARS); - assertThat(organization.getDescription()).isEqualTo(login + "'s personal organization"); - } - @Test public void createForUser_associates_to_built_in_quality_profiles() { UserDto user = db.users().insertUser(A_LOGIN); @@ -536,7 +488,6 @@ public class OrganizationUpdaterImplTest { assertThat(db.countRowsOfTable("perm_templates_groups")).isEqualTo(0); } - @Test public void update_personal_organization() { OrganizationDto organization = db.organizations().insert(o -> o.setKey("old login")); diff --git a/server/sonar-server/src/test/java/org/sonar/server/organization/OrganizationValidationImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/organization/OrganizationValidationImplTest.java index edd43f5fe01..cda78442412 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/organization/OrganizationValidationImplTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/organization/OrganizationValidationImplTest.java @@ -19,6 +19,7 @@ */ package org.sonar.server.organization; +import com.google.common.base.Strings; import java.util.Random; import org.junit.Rule; import org.junit.Test; @@ -32,6 +33,8 @@ public class OrganizationValidationImplTest { 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_300_CHARS = Strings.repeat("a", 300); + @Rule public ExpectedException expectedException = ExpectedException.none(); @@ -62,27 +65,22 @@ public class OrganizationValidationImplTest { } @Test - public void checkValidKey_does_not_fail_if_arg_is_2_to_32_chars_long() { - String str = "aa"; - for (int i = 0; i < 31; i++) { + public void checkValidKey_does_not_fail_if_arg_is_1_to_300_chars_long() { + String str = "a"; + for (int i = 0; i < 299; i++) { underTest.checkKey(str); str += "a"; } } @Test - public void checkValidKey_throws_IAE_if_arg_is_33_or_more_chars_long() { - String str = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; - underTest.checkKey(str); - for (int i = 0; i < 5 + Math.abs(new Random().nextInt(10)); i++) { - str += "c"; - try { - underTest.checkKey(str); - fail("A IllegalArgumentException should have been thrown"); - } catch (IllegalArgumentException e) { - assertThat(e).hasMessage("Key '" + str + "' must be at most 32 chars long"); - } - } + public void checkValidKey_throws_IAE_when_more_than_300_characters() { + String key = STRING_300_CHARS + "b"; + + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("Key '" + key + "' must be at most 300 chars long"); + + underTest.checkKey(key); } @Test @@ -117,27 +115,22 @@ public class OrganizationValidationImplTest { } @Test - public void checkValidName_does_not_fail_if_arg_is_2_to_32_chars_long() { - String str = "aa"; - for (int i = 0; i < 63; i++) { + public void checkValidName_does_not_fail_if_arg_is_1_to_300_chars_long() { + String str = "a"; + for (int i = 0; i < 299; i++) { underTest.checkName(str); str += "a"; } } @Test - public void checkValidName_throws_IAE_if_arg_is_65_or_more_chars_long() { - String str = STRING_64_CHARS; + public void checkValidName_throws_IAE_when_more_than_300_characters() { + String str = STRING_300_CHARS + "b"; + + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("Name '" + str + "' must be at most 300 chars long"); + underTest.checkName(str); - for (int i = 0; i < 5 + Math.abs(new Random().nextInt(10)); i++) { - str += "c"; - try { - underTest.checkName(str); - fail("A IllegalArgumentException should have been thrown"); - } catch (IllegalArgumentException e) { - assertThat(e).hasMessage("Name '" + str + "' must be at most 64 chars long"); - } - } } @Test @@ -244,10 +237,4 @@ public class OrganizationValidationImplTest { assertThat(underTest.generateKeyFrom("<\"foo:\">")).isEqualTo("foo"); } - @Test - public void generateKeyFrom_truncate_arg_to_32_chars() { - assertThat(underTest.generateKeyFrom(STRING_64_CHARS)) - .isEqualTo(underTest.generateKeyFrom(STRING_256_CHARS)) - .isEqualTo(underTest.generateKeyFrom(STRING_32_CHARS)); - } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/organization/ws/CreateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/organization/ws/CreateActionTest.java index 8ce1370500e..3c98626eaeb 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/organization/ws/CreateActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/organization/ws/CreateActionTest.java @@ -69,7 +69,6 @@ import static org.elasticsearch.index.query.QueryBuilders.boolQuery; import static org.elasticsearch.index.query.QueryBuilders.termQuery; import static org.mockito.Mockito.mock; import static org.sonar.core.config.CorePropertyDefinitions.ORGANIZATIONS_ANYONE_CAN_CREATE; -import static org.sonar.server.organization.ws.OrganizationsWsSupport.PARAM_KEY; import static org.sonar.server.organization.ws.OrganizationsWsSupport.PARAM_NAME; import static org.sonar.server.organization.ws.OrganizationsWsTestSupport.STRING_257_CHARS_LONG; import static org.sonar.server.organization.ws.OrganizationsWsTestSupport.STRING_65_CHARS_LONG; @@ -280,16 +279,6 @@ public class CreateActionTest { verifyResponseAndDb(executeRequest("ab"), "ab", "ab", NOW); } - @Test - public void request_succeeds_if_name_is_64_char_long() { - createUserAndLogInAsSystemAdministrator(); - db.qualityGates().insertBuiltInQualityGate(); - - String name = STRING_65_CHARS_LONG.substring(0, 64); - - verifyResponseAndDb(executeRequest(name), name, name.substring(0, 32), NOW); - } - @Test public void request_succeeds_if_key_is_2_chars_long() { createUserAndLogInAsSystemAdministrator(); @@ -327,17 +316,6 @@ public class CreateActionTest { verifyResponseAndDb(response, "foo", "bar", "moo", "doo", "boo", NOW); } - @Test - public void request_succeeds_to_generate_key_from_name_more_then_32_chars_long() { - createUserAndLogInAsSystemAdministrator(); - db.qualityGates().insertBuiltInQualityGate(); - - String name = STRING_65_CHARS_LONG.substring(0, 33); - - CreateWsResponse response = executeRequest(name); - verifyResponseAndDb(response, name, name.substring(0, 32), NOW); - } - @Test public void request_generates_key_ignoring_multiple_following_spaces() { createUserAndLogInAsSystemAdministrator(); @@ -389,40 +367,6 @@ public class CreateActionTest { executeRequest(null); } - @Test - public void request_fails_if_name_is_empty() { - createUserAndLogInAsSystemAdministrator(); - - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage("Name must not be empty"); - - wsTester.newRequest() - .setParam(PARAM_NAME, "") - .execute(); - } - - @Test - public void request_fails_if_name_is_65_chars_long() { - createUserAndLogInAsSystemAdministrator(); - - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage("'name' length (65) is longer than the maximum authorized (64)"); - - executeRequest(STRING_65_CHARS_LONG); - } - - @Test - public void request_fails_if_key_is_33_chars_long() { - createUserAndLogInAsSystemAdministrator(); - - String key = STRING_65_CHARS_LONG.substring(0, 33); - - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage("'key' length (33) is longer than the maximum authorized (32)"); - - executeRequest("foo", key); - } - @Test public void requests_fails_if_key_contains_non_ascii_chars_but_dash() { createUserAndLogInAsSystemAdministrator(); @@ -463,19 +407,6 @@ public class CreateActionTest { executeRequest("foo", "a b"); } - @Test - public void request_fails_if_key_is_empty() { - createUserAndLogInAsSystemAdministrator(); - - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage("Key must not be empty"); - - wsTester.newRequest() - .setParam(PARAM_KEY, "") - .setParam(PARAM_NAME, "foo") - .execute(); - } - @Test public void request_fails_if_key_is_specified_and_already_exists_in_DB() { createUserAndLogInAsSystemAdministrator(); @@ -490,9 +421,9 @@ public class CreateActionTest { @Test public void request_fails_if_key_computed_from_name_already_exists_in_DB() { createUserAndLogInAsSystemAdministrator(); - String key = STRING_65_CHARS_LONG.substring(0, 32); + String key = "key"; db.organizations().insert(o -> o.setKey(key)); - String name = STRING_65_CHARS_LONG.substring(0, 64); + String name = "Key"; expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage("Key '" + key + "' generated from name '" + name + "' is already used. Specify one."); @@ -584,13 +515,18 @@ public class CreateActionTest { assertThat(action.handler()).isNotNull(); assertThat(action.params()).hasSize(5); assertThat(action.responseExample()).isEqualTo(getClass().getResource("create-example.json")); + assertThat(action.param("name")) .matches(WebService.Param::isRequired) .matches(param -> "Foo Company".equals(param.exampleValue())) + .matches(param -> param.minimumLength().equals(1)) + .matches(param -> param.maximumLength().equals(300)) .matches(param -> param.description() != null); assertThat(action.param("key")) .matches(param -> !param.isRequired()) .matches(param -> "foo-company".equals(param.exampleValue())) + .matches(param -> param.minimumLength().equals(1)) + .matches(param -> param.maximumLength().equals(300)) .matches(param -> param.description() != null); assertThat(action.param("description")) .matches(param -> !param.isRequired()) diff --git a/server/sonar-server/src/test/java/org/sonar/server/organization/ws/UpdateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/organization/ws/UpdateActionTest.java index d4e898dacd1..74867b34a59 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/organization/ws/UpdateActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/organization/ws/UpdateActionTest.java @@ -82,6 +82,8 @@ public class UpdateActionTest { assertThat(action.param("name")) .matches(param -> !param.isRequired()) .matches(param -> "Foo Company".equals(param.exampleValue())) + .matches(param -> param.minimumLength().equals(1)) + .matches(param -> param.maximumLength().equals(300)) .matches(param -> param.description() != null); assertThat(action.param("description")) .matches(param -> !param.isRequired()) @@ -172,16 +174,6 @@ public class UpdateActionTest { verifyResponseAndDb(executeKeyRequest(org.getKey(), null), org, org.getName(), DATE_2); } - @Test - public void request_fails_if_name_is_empty() { - userSession.logIn(); - - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage("Name must not be empty"); - - executeKeyRequest(SOME_KEY, ""); - } - @Test public void request_succeeds_if_name_is_two_chars_long() { OrganizationDto org = mockForSuccessfulUpdate(DATE_1, DATE_2); @@ -190,17 +182,6 @@ public class UpdateActionTest { verifyResponseAndDb(executeKeyRequest(org.getKey(), "ab"), org, "ab", DATE_2); } - @Test - public void request_fails_if_name_is_65_chars_long() { - userSession.logIn(); - - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage("'name' length (65) is longer than the maximum authorized (64)"); - - - executeKeyRequest(SOME_KEY, STRING_65_CHARS_LONG); - } - @Test public void request_succeeds_if_name_is_64_char_long() { OrganizationDto org = mockForSuccessfulUpdate(DATE_1, DATE_2); -- 2.39.5