diff --git a/api/src/main/java/com/epam/pipeline/entity/git/AuthType.java b/api/src/main/java/com/epam/pipeline/entity/git/AuthType.java new file mode 100644 index 0000000000..ea4e3babe9 --- /dev/null +++ b/api/src/main/java/com/epam/pipeline/entity/git/AuthType.java @@ -0,0 +1,21 @@ +/* + * Copyright 2024 EPAM Systems, Inc. (https://www.epam.com/) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.epam.pipeline.entity.git; + +public enum AuthType { + TOKEN, BASIC; +} diff --git a/api/src/main/java/com/epam/pipeline/manager/git/bitbucketcloud/BitbucketCloudService.java b/api/src/main/java/com/epam/pipeline/manager/git/bitbucketcloud/BitbucketCloudService.java index fd1fa240c9..546dea3ec4 100644 --- a/api/src/main/java/com/epam/pipeline/manager/git/bitbucketcloud/BitbucketCloudService.java +++ b/api/src/main/java/com/epam/pipeline/manager/git/bitbucketcloud/BitbucketCloudService.java @@ -20,6 +20,7 @@ import com.epam.pipeline.common.MessageHelper; import com.epam.pipeline.controller.vo.PipelineSourceItemsVO; import com.epam.pipeline.controller.vo.UploadFileMetadata; +import com.epam.pipeline.entity.git.AuthType; import com.epam.pipeline.entity.git.GitCommitEntry; import com.epam.pipeline.entity.git.GitCredentials; import com.epam.pipeline.entity.git.GitProject; @@ -41,7 +42,6 @@ import com.epam.pipeline.manager.preference.PreferenceManager; import com.epam.pipeline.manager.preference.SystemPreferences; import com.epam.pipeline.mapper.git.BitbucketCloudMapper; -import com.epam.pipeline.utils.AuthorizationUtils; import com.epam.pipeline.utils.GitUtils; import joptsimple.internal.Strings; import lombok.RequiredArgsConstructor; @@ -59,16 +59,22 @@ import java.util.stream.Collectors; import static com.epam.pipeline.manager.git.PipelineRepositoryService.NOT_SUPPORTED_PATTERN; +import static com.epam.pipeline.utils.AuthorizationUtils.buildBasicAuth; +import static com.epam.pipeline.utils.AuthorizationUtils.buildBearerTokenAuth; @Service @RequiredArgsConstructor public class BitbucketCloudService implements GitClientService { + private static final String REPOSITORY_NAME = "repository name"; private static final String PROJECT_NAME = "project name"; + private static final String USER_NAME = "user name"; + private static final String X_TOKEN_AUTH = "x-token-auth"; private static final String BITBUCKET_CLOUD_FOLDER_MARKER = "commit_directory"; private static final String BITBUCKET_CLOUD_FILE_MARKER = "commit_file"; - private static final int MAX_DEPTH = 20; private static final String PAGE_PARAMETER = "page="; + private static final int MAX_DEPTH = 20; + private final BitbucketCloudMapper mapper; private final MessageHelper messageHelper; private final PreferenceManager preferenceManager; @@ -201,7 +207,9 @@ public GitCredentials getCloneCredentials(final Pipeline pipeline, final boolean final boolean issueToken, final Long duration) { final GitRepositoryUrl repositoryUrl = GitRepositoryUrl.from(pipeline.getRepository()); final String token = pipeline.getRepositoryToken(); - final String username = preferenceManager.getPreference(SystemPreferences.BITBUCKET_CLOUD_USER_NAME); + final AuthType authType = preferenceManager.getPreference(SystemPreferences.BITBUCKET_CLOUD_AUTH_TYPE); + final String username = AuthType.TOKEN.equals(authType) ? X_TOKEN_AUTH : + repositoryUrl.getUsername().orElseThrow(() -> buildUrlParseError(USER_NAME)); final String host = repositoryUrl.getHost(); return GitCredentials.builder() .url(GitRepositoryUrl.asString(repositoryUrl.getProtocol(), username, token, host, @@ -351,7 +359,11 @@ private BitbucketCloudClient buildClient(final String repositoryPath, final Stri Assert.isTrue(StringUtils.isNotBlank(token), messageHelper .getMessage(MessageConstants.ERROR_BITBUCKET_CLOUD_TOKEN_NOT_FOUND)); - final String credentials = AuthorizationUtils.BEARER_AUTH + token; + final AuthType authType = preferenceManager.getPreference(SystemPreferences.BITBUCKET_CLOUD_AUTH_TYPE); + final String credentials = AuthType.TOKEN.equals(authType) ? + buildBearerTokenAuth(token) : + buildBasicAuth(repositoryUrl.getUsername().orElseThrow(() -> buildUrlParseError(USER_NAME)), token); + final String apiVersion = preferenceManager.getPreference(SystemPreferences.BITBUCKET_CLOUD_API_VERSION); return new BitbucketCloudClient(bitbucketHost, credentials, null, diff --git a/api/src/main/java/com/epam/pipeline/manager/preference/SystemPreferences.java b/api/src/main/java/com/epam/pipeline/manager/preference/SystemPreferences.java index fa291b7369..fecaa9b076 100644 --- a/api/src/main/java/com/epam/pipeline/manager/preference/SystemPreferences.java +++ b/api/src/main/java/com/epam/pipeline/manager/preference/SystemPreferences.java @@ -32,6 +32,7 @@ import com.epam.pipeline.entity.datastorage.StorageQuotaAction; import com.epam.pipeline.entity.datastorage.nfs.NFSMountPolicy; import com.epam.pipeline.entity.execution.OSSpecificLaunchCommandTemplate; +import com.epam.pipeline.entity.git.AuthType; import com.epam.pipeline.entity.git.GitlabIssueLabelsFilter; import com.epam.pipeline.entity.git.GitlabIssueVisibility; import com.epam.pipeline.entity.git.GitlabVersion; @@ -361,11 +362,11 @@ public class SystemPreferences { public static final StringPreference BITBUCKET_DEFAULT_DOC_DIRECTORY = new StringPreference( "bitbucket.default.doc.directory", null, GIT_GROUP, pass, true); - public static final StringPreference GITHUB_USER_NAME = - new StringPreference("github.user.name", null, GIT_GROUP, pass); + public static final StringPreference GITHUB_USER_NAME = new StringPreference( + "github.user.name", null, GIT_GROUP, pass); - public static final StringPreference BITBUCKET_CLOUD_USER_NAME = - new StringPreference("bitbucket.cloud.user.name", null, GIT_GROUP, pass); + public static final EnumPreference BITBUCKET_CLOUD_AUTH_TYPE = new EnumPreference<>( + "bitbucket.cloud.auth.type", AuthType.BASIC, GIT_GROUP, pass); public static final StringPreference BITBUCKET_CLOUD_API_VERSION = new StringPreference( "bitbucket.cloud.api.version", "2.0", GIT_GROUP, pass); public static final StringPreference GITLAB_PROJECT_VISIBILITY = new StringPreference( diff --git a/api/src/test/java/com/epam/pipeline/manager/git/BitbucketCloudServiceTest.java b/api/src/test/java/com/epam/pipeline/manager/git/BitbucketCloudServiceTest.java index 3af58d047e..d317d2e786 100644 --- a/api/src/test/java/com/epam/pipeline/manager/git/BitbucketCloudServiceTest.java +++ b/api/src/test/java/com/epam/pipeline/manager/git/BitbucketCloudServiceTest.java @@ -17,31 +17,50 @@ package com.epam.pipeline.manager.git; import com.epam.pipeline.AbstractSpringTest; +import com.epam.pipeline.entity.git.AuthType; import com.epam.pipeline.entity.git.GitCommitEntry; import com.epam.pipeline.entity.git.GitProject; import com.epam.pipeline.entity.git.GitRepositoryEntry; import com.epam.pipeline.entity.git.GitTagEntry; import com.epam.pipeline.entity.pipeline.Pipeline; import com.epam.pipeline.entity.pipeline.Revision; +import com.epam.pipeline.entity.preference.Preference; import com.epam.pipeline.exception.git.GitClientException; import com.epam.pipeline.manager.git.bitbucketcloud.BitbucketCloudService; +import com.epam.pipeline.manager.preference.PreferenceManager; +import com.epam.pipeline.manager.preference.SystemPreferences; import org.junit.Assert; +import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import java.util.Collections; import java.util.List; public class BitbucketCloudServiceTest extends AbstractSpringTest { private static final String BRANCH = "test"; - private static final String TAG = "test_tag10"; + private static final String TAG = "test_tag1"; private static final String MESSAGE = "message"; - private static final String COMMIT_ID = "d468da2"; + private static final String COMMIT_ID = "c4cbce0"; private static final String FILE_PATH = "/test2/test_file.txt"; private static final String FOLDER_PATH = "test2"; private static final String CONTENT = "content123"; + +/* + Authentication type should be set up in System Preferences(bitbucket.cloud.auth.type). + If Authentication type is BASIC: + repositoryPath should contain user name (like https://user_name@bitbucket.org/workspace/repository.git) + token should contain app password + Clone url looks like https://user_name:password@bitbucket.org/workspace/repository.git + + If Authentication type is TOKEN: + repositoryPath should look like https://bitbucket.org/workspace/repository.git + token should contain secure token + Clone url looks like https://x-token-auth:token@bitbucket.org/workspace/repository.git +*/ @Value("${bitbucket.cloud.repository.path}") private String repositoryPath; @Value("${bitbucket.cloud.token}") @@ -50,6 +69,16 @@ public class BitbucketCloudServiceTest extends AbstractSpringTest { @Autowired private BitbucketCloudService service; + @Autowired + private PreferenceManager preferenceManager; + + @Before + public void setup() { + final Preference preference = SystemPreferences.BITBUCKET_CLOUD_AUTH_TYPE.toPreference(); + preference.setValue(AuthType.TOKEN.name()); + preferenceManager.update(Collections.singletonList(preference)); + } + @Ignore @Test public void testGetRepository() throws GitClientException {