private String projectName;
+ private String projectUuid;
+
public String getUuid() {
return uuid;
}
this.projectName = projectName;
return this;
}
+
+ public String getProjectUuid() {
+ return projectUuid;
+ }
+
+ public void setProjectUuid(String projectUuid) {
+ this.projectUuid = projectUuid;
+ }
}
t.created_at as "createdAt",
t.project_key as "projectKey",
t.type as "type",
- p.name as "projectName"
+ p.name as "projectName",
+ p.uuid as "projectUuid"
</sql>
<insert id="insert" parameterType="UserToken" useGeneratedKeys="false">
assertThat(projectAnalysisTokenFromDb.getCreatedAt()).isEqualTo(projectAnalysisToken.getCreatedAt());
assertThat(projectAnalysisTokenFromDb.getTokenHash()).isEqualTo(projectAnalysisToken.getTokenHash());
assertThat(projectAnalysisTokenFromDb.getUserUuid()).isEqualTo(projectAnalysisToken.getUserUuid());
+ assertThat(projectAnalysisTokenFromDb.getProjectUuid()).isEqualTo(project.uuid());
assertThat(projectAnalysisTokenFromDb.getProjectKey()).isEqualTo(projectAnalysisToken.getProjectKey());
assertThat(projectAnalysisTokenFromDb.getType()).isEqualTo(projectAnalysisToken.getType());
assertThat(projectAnalysisTokenFromDb.getProjectName()).isEqualTo(project.name());
import java.util.Base64;
import java.util.Optional;
import javax.servlet.http.HttpServletRequest;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
import org.sonar.db.user.UserDto;
import org.sonar.server.authentication.event.AuthenticationEvent;
import org.sonar.server.authentication.event.AuthenticationException;
import static org.apache.commons.lang.StringUtils.startsWithIgnoreCase;
import static org.sonar.server.authentication.event.AuthenticationEvent.Method;
import static org.sonar.server.authentication.event.AuthenticationEvent.Source;
-import static org.sonar.server.usertoken.UserTokenAuthentication.PROJECT_KEY_SCANNER_HEADER;
/**
* HTTP BASIC authentication relying on tuple {login, password}.
*/
public class BasicAuthentication {
- private static final String ACCESS_LOG_TOKEN_NAME = "TOKEN_NAME";
-
- private final DbClient dbClient;
private final CredentialsAuthentication credentialsAuthentication;
private final UserTokenAuthentication userTokenAuthentication;
- private final AuthenticationEvent authenticationEvent;
- public BasicAuthentication(DbClient dbClient, CredentialsAuthentication credentialsAuthentication,
- UserTokenAuthentication userTokenAuthentication, AuthenticationEvent authenticationEvent) {
- this.dbClient = dbClient;
+ public BasicAuthentication(CredentialsAuthentication credentialsAuthentication, UserTokenAuthentication userTokenAuthentication) {
this.credentialsAuthentication = credentialsAuthentication;
this.userTokenAuthentication = userTokenAuthentication;
- this.authenticationEvent = authenticationEvent;
}
public Optional<UserDto> authenticate(HttpServletRequest request) {
return extractCredentialsFromHeader(request)
- .flatMap(credentials -> Optional.of(authenticate(credentials, request)));
+ .flatMap(credentials -> Optional.ofNullable(authenticate(credentials, request)));
}
public static Optional<Credentials> extractCredentialsFromHeader(HttpServletRequest request) {
private UserDto authenticate(Credentials credentials, HttpServletRequest request) {
if (credentials.getPassword().isEmpty()) {
- String projectKeyScannerHeader = request.getHeader(PROJECT_KEY_SCANNER_HEADER);
- UserDto userDto = authenticateFromUserToken(credentials.getLogin(), request, projectKeyScannerHeader);
- authenticationEvent.loginSuccess(request, userDto.getLogin(), Source.local(Method.BASIC_TOKEN));
- return userDto;
- }
- return credentialsAuthentication.authenticate(credentials, request, Method.BASIC);
- }
-
- private UserDto authenticateFromUserToken(String token, HttpServletRequest request, String projectKey) {
- String path = request.getRequestURI().substring(request.getContextPath().length());
- UserTokenAuthentication.UserTokenAuthenticationResult result = userTokenAuthentication.authenticate(token, path, projectKey);
- if (result.getErrorMessage() != null) {
- throw AuthenticationException.newBuilder()
- .setSource(Source.local(Method.BASIC_TOKEN))
- .setMessage(result.getErrorMessage())
- .build();
- }
- try (DbSession dbSession = dbClient.openSession(false)) {
- UserDto userDto = dbClient.userDao().selectByUuid(dbSession, result.getAuthenticatedUserUuid());
- if (userDto == null || !userDto.isActive()) {
+ Optional<UserAuthResult> userAuthResult = userTokenAuthentication.authenticate(request);
+ if (userAuthResult.isPresent()) {
+ return userAuthResult.get().getUserDto();
+ } else {
throw AuthenticationException.newBuilder()
- .setSource(Source.local(Method.BASIC_TOKEN))
+ .setSource(AuthenticationEvent.Source.local(AuthenticationEvent.Method.BASIC_TOKEN))
.setMessage("User doesn't exist")
.build();
}
- request.setAttribute(ACCESS_LOG_TOKEN_NAME, result.getTokenName());
- return userDto;
}
+ return credentialsAuthentication.authenticate(credentials, request, Method.BASIC);
}
}
package org.sonar.server.authentication;
import com.google.common.base.Splitter;
-import com.google.common.collect.ImmutableMap;
import java.util.Collections;
import java.util.Date;
import java.util.EnumSet;
}
UserDto userDto = doAuthenticate(headerValuesByNames, login);
- jwtHttpHandler.generateToken(userDto, ImmutableMap.of(LAST_REFRESH_TIME_TOKEN_PARAM, system2.now()), request, response);
+ jwtHttpHandler.generateToken(userDto, Map.of(LAST_REFRESH_TIME_TOKEN_PARAM, system2.now()), request, response);
authenticationEvent.loginSuccess(request, userDto.getLogin(), Source.sso());
return Optional.of(userDto);
}
private Optional<UserDto> getUserFromToken(HttpServletRequest request, HttpServletResponse response) {
Optional<JwtHttpHandler.Token> token = jwtHttpHandler.getToken(request, response);
- if (!token.isPresent()) {
+ if (token.isEmpty()) {
return Optional.empty();
}
Date now = new Date(system2.now());
import org.sonar.db.user.UserDto;
import org.sonar.server.user.UserSession;
import org.sonar.server.user.UserSessionFactory;
+import org.sonar.server.usertoken.UserTokenAuthentication;
import org.springframework.beans.factory.annotation.Autowired;
+import static java.util.Objects.nonNull;
+import static org.sonar.server.authentication.UserAuthResult.AuthType.BASIC;
+import static org.sonar.server.authentication.UserAuthResult.AuthType.JWT;
+import static org.sonar.server.authentication.UserAuthResult.AuthType.SSO;
+import static org.sonar.server.authentication.UserAuthResult.AuthType.TOKEN;
+
public class RequestAuthenticatorImpl implements RequestAuthenticator {
private final JwtHttpHandler jwtHttpHandler;
private final BasicAuthentication basicAuthentication;
+ private final UserTokenAuthentication userTokenAuthentication;
private final HttpHeadersAuthentication httpHeadersAuthentication;
private final UserSessionFactory userSessionFactory;
private final List<CustomAuthentication> customAuthentications;
@Autowired(required = false)
- public RequestAuthenticatorImpl(JwtHttpHandler jwtHttpHandler, BasicAuthentication basicAuthentication, HttpHeadersAuthentication httpHeadersAuthentication,
+ public RequestAuthenticatorImpl(JwtHttpHandler jwtHttpHandler, BasicAuthentication basicAuthentication, UserTokenAuthentication userTokenAuthentication,
+ HttpHeadersAuthentication httpHeadersAuthentication,
UserSessionFactory userSessionFactory, CustomAuthentication[] customAuthentications) {
this.jwtHttpHandler = jwtHttpHandler;
this.basicAuthentication = basicAuthentication;
+ this.userTokenAuthentication = userTokenAuthentication;
this.httpHeadersAuthentication = httpHeadersAuthentication;
this.userSessionFactory = userSessionFactory;
this.customAuthentications = Arrays.asList(customAuthentications);
}
@Autowired(required = false)
- public RequestAuthenticatorImpl(JwtHttpHandler jwtHttpHandler, BasicAuthentication basicAuthentication, HttpHeadersAuthentication httpHeadersAuthentication,
+ public RequestAuthenticatorImpl(JwtHttpHandler jwtHttpHandler, BasicAuthentication basicAuthentication, UserTokenAuthentication userTokenAuthentication,
+ HttpHeadersAuthentication httpHeadersAuthentication,
UserSessionFactory userSessionFactory) {
- this(jwtHttpHandler, basicAuthentication, httpHeadersAuthentication, userSessionFactory, new CustomAuthentication[0]);
+ this(jwtHttpHandler, basicAuthentication, userTokenAuthentication, httpHeadersAuthentication, userSessionFactory, new CustomAuthentication[0]);
}
@Override
}
}
- Optional<UserDto> userOpt = loadUser(request, response);
- if (userOpt.isPresent()) {
- return userSessionFactory.create(userOpt.get());
+ UserAuthResult userAuthResult = loadUser(request, response);
+ if (nonNull(userAuthResult.getUserDto())) {
+ if (TOKEN.equals(userAuthResult.getAuthType())) {
+ return userSessionFactory.create(userAuthResult.getUserDto(), userAuthResult.getTokenDto());
+ }
+ return userSessionFactory.create(userAuthResult.getUserDto());
}
return userSessionFactory.createAnonymous();
}
- private Optional<UserDto> loadUser(HttpServletRequest request, HttpServletResponse response) {
+ private UserAuthResult loadUser(HttpServletRequest request, HttpServletResponse response) {
// Try first to authenticate from SSO, then JWT token, then try from basic http header
// SSO authentication should come first in order to update JWT if user from header is not the same is user from JWT
Optional<UserDto> user = httpHeadersAuthentication.authenticate(request, response);
if (user.isPresent()) {
- return user;
+ return new UserAuthResult(user.get(), SSO);
}
user = jwtHttpHandler.validateToken(request, response);
if (user.isPresent()) {
- return user;
+ return new UserAuthResult(user.get(), JWT);
+ }
+
+ // Check if the authentication is token based
+ Optional<UserAuthResult> userAuthResult = userTokenAuthentication.authenticate(request);
+ if (userAuthResult.isPresent()) {
+ return userAuthResult.get();
}
- return basicAuthentication.authenticate(request);
+
+ user = basicAuthentication.authenticate(request);
+ return user.map(userDto -> new UserAuthResult(userDto, BASIC))
+ .orElseGet(UserAuthResult::new);
}
+
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 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.authentication;
+
+import org.sonar.db.user.UserDto;
+import org.sonar.db.user.UserTokenDto;
+
+public class UserAuthResult {
+
+ public enum AuthType {
+ SSO,
+ JWT,
+ TOKEN,
+ BASIC
+ }
+
+ UserDto userDto;
+ UserTokenDto tokenDto;
+ AuthType authType;
+
+ public UserAuthResult() {
+ }
+
+ public UserAuthResult(UserDto userDto, AuthType authType) {
+ this.userDto = userDto;
+ this.authType = authType;
+ }
+
+ public UserAuthResult(UserDto userDto, UserTokenDto tokenDto, AuthType authType) {
+ this.userDto = userDto;
+ this.tokenDto = tokenDto;
+ this.authType = authType;
+ }
+
+ public UserDto getUserDto() {
+ return userDto;
+ }
+
+ public AuthType getAuthType() {
+ return authType;
+ }
+
+ public UserTokenDto getTokenDto() {
+ return tokenDto;
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 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.user;
+
+import org.sonar.db.DbClient;
+import org.sonar.db.permission.GlobalPermission;
+import org.sonar.db.user.TokenType;
+import org.sonar.db.user.UserDto;
+import org.sonar.db.user.UserTokenDto;
+
+public class TokenUserSession extends ServerUserSession {
+
+ private static final String SCAN = "scan";
+ private final UserTokenDto userToken;
+
+ public TokenUserSession(DbClient dbClient, UserDto user, UserTokenDto userToken) {
+ super(dbClient, user);
+ this.userToken = userToken;
+ }
+
+ @Override
+ protected boolean hasProjectUuidPermission(String permission, String projectUuid) {
+ TokenType tokenType = TokenType.valueOf(userToken.getType());
+ switch (tokenType) {
+ case USER_TOKEN:
+ return super.hasProjectUuidPermission(permission, projectUuid);
+ case PROJECT_ANALYSIS_TOKEN:
+ return SCAN.equals(permission) &&
+ projectUuid.equals(userToken.getProjectUuid()) &&
+ (super.hasProjectUuidPermission(SCAN, projectUuid) || super.hasPermissionImpl(GlobalPermission.SCAN));
+ case GLOBAL_ANALYSIS_TOKEN:
+ //The case with a global analysis token has to return false always, since it is based on the assumption that the user
+ // has global analysis privileges
+ return false;
+ default:
+ throw new IllegalArgumentException("Unsupported token type " + tokenType.name());
+ }
+
+ }
+
+ @Override
+ protected boolean hasPermissionImpl(GlobalPermission permission) {
+ TokenType tokenType = TokenType.valueOf(userToken.getType());
+ switch (tokenType) {
+ case USER_TOKEN:
+ return super.hasPermissionImpl(permission);
+ case PROJECT_ANALYSIS_TOKEN:
+ //The case with a project analysis token has to return false always, delegating the result to the super class would allow
+ //the project analysis token to work for multiple projects in case the user has Global Permissions.
+ return false;
+ case GLOBAL_ANALYSIS_TOKEN:
+ return GlobalPermission.SCAN.equals(permission) &&
+ super.hasPermissionImpl(permission);
+ default:
+ throw new IllegalArgumentException("Unsupported token type " + tokenType.name());
+ }
+ }
+
+}
import org.sonar.api.server.ServerSide;
import org.sonar.db.user.UserDto;
+import org.sonar.db.user.UserTokenDto;
@ServerSide
public interface UserSessionFactory {
UserSession create(UserDto user);
+ UserSession create(UserDto user, UserTokenDto userToken);
+
UserSession createAnonymous();
}
import org.sonar.api.server.ServerSide;
import org.sonar.db.DbClient;
import org.sonar.db.user.UserDto;
+import org.sonar.db.user.UserTokenDto;
import org.sonar.server.authentication.UserLastConnectionDatesUpdater;
import static java.util.Objects.requireNonNull;
return new ServerUserSession(dbClient, user);
}
+ @Override
+ public TokenUserSession create(UserDto user, UserTokenDto userToken) {
+ requireNonNull(user, "UserDto must not be null");
+ requireNonNull(userToken, "UserTokenDto must not be null");
+ userLastConnectionDatesUpdater.updateLastConnectionDateIfNeeded(user);
+ return new TokenUserSession(dbClient, user, userToken);
+ }
+
@Override
public ServerUserSession createAnonymous() {
return new ServerUserSession(dbClient, null);
*/
package org.sonar.server.usertoken;
-import java.util.EnumMap;
-import java.util.Set;
+import java.util.Optional;
import javax.annotation.Nullable;
+import javax.servlet.http.HttpServletRequest;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
-import org.sonar.db.user.TokenType;
+import org.sonar.db.user.UserDto;
import org.sonar.db.user.UserTokenDto;
+import org.sonar.server.authentication.Credentials;
+import org.sonar.server.authentication.UserAuthResult;
import org.sonar.server.authentication.UserLastConnectionDatesUpdater;
+import org.sonar.server.authentication.event.AuthenticationEvent;
+import org.sonar.server.authentication.event.AuthenticationException;
+import org.sonar.server.exceptions.NotFoundException;
-public class UserTokenAuthentication {
-
- public static final String PROJECT_KEY_SCANNER_HEADER = "PROJECT_KEY";
-
- private static final Set<String> SCANNER_ENDPOINTS = Set.of(
- "/api/settings/values",
- "/api/plugins/installed",
- "/api/analysis_cache/get",
- "/api/project_branches/list",
- "/api/project_pull_requests/list",
- "/api/qualityprofiles/search",
- "/api/rules/search",
- "/batch/project",
- "/api/metrics/search",
- "/api/new_code_periods/show",
- "/api/ce/submit");
+import static org.sonar.server.authentication.BasicAuthentication.extractCredentialsFromHeader;
- private static final EnumMap<TokenType, Set<String>> ALLOWLIST_ENDPOINTS_FOR_TOKEN_TYPES = new EnumMap<>(TokenType.class);
-
- static {
- ALLOWLIST_ENDPOINTS_FOR_TOKEN_TYPES.put(TokenType.GLOBAL_ANALYSIS_TOKEN, SCANNER_ENDPOINTS);
- ALLOWLIST_ENDPOINTS_FOR_TOKEN_TYPES.put(TokenType.PROJECT_ANALYSIS_TOKEN, SCANNER_ENDPOINTS);
- }
+public class UserTokenAuthentication {
+ private static final String ACCESS_LOG_TOKEN_NAME = "TOKEN_NAME";
private final TokenGenerator tokenGenerator;
private final DbClient dbClient;
private final UserLastConnectionDatesUpdater userLastConnectionDatesUpdater;
+ private final AuthenticationEvent authenticationEvent;
- public UserTokenAuthentication(TokenGenerator tokenGenerator, DbClient dbClient, UserLastConnectionDatesUpdater userLastConnectionDatesUpdater) {
+ public UserTokenAuthentication(TokenGenerator tokenGenerator, DbClient dbClient, UserLastConnectionDatesUpdater userLastConnectionDatesUpdater,
+ AuthenticationEvent authenticationEvent) {
this.tokenGenerator = tokenGenerator;
this.dbClient = dbClient;
this.userLastConnectionDatesUpdater = userLastConnectionDatesUpdater;
+ this.authenticationEvent = authenticationEvent;
}
- /**
- * Returns the user token details including if the token hash is found and the user has provided valid token type.
- *
- * The returned uuid included in the UserTokenAuthenticationResult is not validated. If database is corrupted
- * (table USER_TOKENS badly purged for instance), then the uuid may not relate to a valid user.
- *
- * In case of any issues only the error message is included in UserTokenAuthenticationResult
- */
- public UserTokenAuthenticationResult authenticate(String token, String requestedEndpoint, @Nullable String analyzedProjectKey) {
- String tokenHash = tokenGenerator.hash(token);
- try (DbSession dbSession = dbClient.openSession(false)) {
- UserTokenDto userToken = dbClient.userTokenDao().selectByTokenHash(dbSession, tokenHash);
- if (userToken == null) {
- return new UserTokenAuthenticationResult("Token doesn't exist");
- }
- if (!isValidTokenType(userToken, analyzedProjectKey, requestedEndpoint)) {
- return new UserTokenAuthenticationResult("Invalid token");
+ public Optional<UserAuthResult> authenticate(HttpServletRequest request) {
+ if (isTokenBasedAuthentication(request)) {
+ Optional<Credentials> credentials = extractCredentialsFromHeader(request);
+ if (credentials.isPresent()) {
+ UserAuthResult userAuthResult = authenticateFromUserToken(credentials.get().getLogin(), request);
+ authenticationEvent.loginSuccess(request, userAuthResult.getUserDto().getLogin(), AuthenticationEvent.Source.local(AuthenticationEvent.Method.BASIC_TOKEN));
+ return Optional.of(userAuthResult);
}
- userLastConnectionDatesUpdater.updateLastConnectionDateIfNeeded(userToken);
- return new UserTokenAuthenticationResult(userToken.getUserUuid(), userToken.getName());
}
+ return Optional.empty();
}
- private static boolean isValidTokenType(UserTokenDto userToken, @Nullable String analyzedProjectKey, String requestedEndpoint) {
- TokenType tokenType = TokenType.valueOf(userToken.getType());
-
- return validateProjectKeyForScannerToken(tokenType, userToken, analyzedProjectKey)
- && shouldBeAbleToAccessEndpoint(tokenType, requestedEndpoint);
+ public static boolean isTokenBasedAuthentication(HttpServletRequest request) {
+ Optional<Credentials> credentialsOptional = extractCredentialsFromHeader(request);
+ return credentialsOptional.map(credentials -> credentials.getPassword().isEmpty()).orElse(false);
}
- private static boolean shouldBeAbleToAccessEndpoint(TokenType tokenType, String requestedEndpoint) {
- Set<String> allowedEndpoints = ALLOWLIST_ENDPOINTS_FOR_TOKEN_TYPES.get(tokenType);
- if (allowedEndpoints == null) {
- return true; // no allowlist configured for the token type - all endpoints are allowed
+ private UserAuthResult authenticateFromUserToken(String token, HttpServletRequest request) {
+ try (DbSession dbSession = dbClient.openSession(false)) {
+ UserTokenDto userToken = authenticate(token);
+ UserDto userDto = dbClient.userDao().selectByUuid(dbSession, userToken.getUserUuid());
+ if (userDto == null || !userDto.isActive()) {
+ throw AuthenticationException.newBuilder()
+ .setSource(AuthenticationEvent.Source.local(AuthenticationEvent.Method.BASIC_TOKEN))
+ .setMessage("User doesn't exist")
+ .build();
+ }
+ request.setAttribute(ACCESS_LOG_TOKEN_NAME, userToken.getName());
+ return new UserAuthResult(userDto, userToken, UserAuthResult.AuthType.TOKEN);
+ } catch (NotFoundException exception) {
+ throw AuthenticationException.newBuilder()
+ .setSource(AuthenticationEvent.Source.local(AuthenticationEvent.Method.BASIC_TOKEN))
+ .setMessage(exception.getMessage())
+ .build();
}
- return allowedEndpoints.stream().anyMatch(requestedEndpoint::startsWith);
}
- private static boolean validateProjectKeyForScannerToken(TokenType tokenType, UserTokenDto userToken, @Nullable String analyzedProjectKey) {
- if (tokenType != TokenType.PROJECT_ANALYSIS_TOKEN) {
- return true;
+ private UserTokenDto authenticate(String token) {
+ UserTokenDto userToken = getUserToken(token);
+ if (userToken == null) {
+ throw new NotFoundException("Token doesn't exist");
}
- return analyzedProjectKey != null && analyzedProjectKey.equals(userToken.getProjectKey());
+ userLastConnectionDatesUpdater.updateLastConnectionDateIfNeeded(userToken);
+ return userToken;
}
- public static class UserTokenAuthenticationResult {
-
- String authenticatedUserUuid;
- String errorMessage;
- String tokenName;
-
- public UserTokenAuthenticationResult(String authenticatedUserUuid, String tokenName) {
- this.authenticatedUserUuid = authenticatedUserUuid;
- this.tokenName = tokenName;
- }
-
- public UserTokenAuthenticationResult(String errorMessage) {
- this.errorMessage = errorMessage;
- }
-
- public String getAuthenticatedUserUuid() {
- return authenticatedUserUuid;
- }
-
- public String getErrorMessage() {
- return errorMessage;
- }
-
- public String getTokenName() {
- return tokenName;
+ @Nullable
+ public UserTokenDto getUserToken(String token) {
+ try (DbSession dbSession = dbClient.openSession(false)) {
+ return dbClient.userTokenDao().selectByTokenHash(dbSession, tokenGenerator.hash(token));
}
-
}
}
import org.junit.Rule;
import org.junit.Test;
import org.sonar.api.utils.System2;
-import org.sonar.db.DbClient;
import org.sonar.db.DbTester;
import org.sonar.db.user.UserDto;
import org.sonar.db.user.UserTesting;
+import org.sonar.db.user.UserTokenDto;
import org.sonar.server.authentication.event.AuthenticationEvent;
import org.sonar.server.authentication.event.AuthenticationException;
import org.sonar.server.usertoken.UserTokenAuthentication;
private static final UserDto USER = UserTesting.newUserDto().setLogin(A_LOGIN);
private static final String EXAMPLE_ENDPOINT = "/api/ce/submit";
+ private static final String AUTHORIZATION_HEADER = "Authorization";
@Rule
public DbTester db = DbTester.create(System2.INSTANCE);
- private DbClient dbClient = db.getDbClient();
+ private final CredentialsAuthentication credentialsAuthentication = mock(CredentialsAuthentication.class);
+ private final UserTokenAuthentication userTokenAuthentication = mock(UserTokenAuthentication.class);
- private CredentialsAuthentication credentialsAuthentication = mock(CredentialsAuthentication.class);
- private UserTokenAuthentication userTokenAuthentication = mock(UserTokenAuthentication.class);
+ private final HttpServletRequest request = mock(HttpServletRequest.class);
- private HttpServletRequest request = mock(HttpServletRequest.class);
+ private final AuthenticationEvent authenticationEvent = mock(AuthenticationEvent.class);
- private AuthenticationEvent authenticationEvent = mock(AuthenticationEvent.class);
-
- private BasicAuthentication underTest = new BasicAuthentication(dbClient, credentialsAuthentication, userTokenAuthentication, authenticationEvent);
+ private final BasicAuthentication underTest = new BasicAuthentication(credentialsAuthentication, userTokenAuthentication);
@Before
public void before() {
@Test
public void authenticate_from_basic_http_header() {
- when(request.getHeader("Authorization")).thenReturn("Basic " + CREDENTIALS_IN_BASE64);
+ when(request.getHeader(AUTHORIZATION_HEADER)).thenReturn("Basic " + CREDENTIALS_IN_BASE64);
Credentials credentials = new Credentials(A_LOGIN, A_PASSWORD);
when(credentialsAuthentication.authenticate(credentials, request, BASIC)).thenReturn(USER);
@Test
public void authenticate_from_basic_http_header_with_password_containing_semi_colon() {
String password = "!ascii-only:-)@";
- when(request.getHeader("Authorization")).thenReturn("Basic " + toBase64(A_LOGIN + ":" + password));
+ when(request.getHeader(AUTHORIZATION_HEADER)).thenReturn("Basic " + toBase64(A_LOGIN + ":" + password));
when(credentialsAuthentication.authenticate(new Credentials(A_LOGIN, password), request, BASIC)).thenReturn(USER);
underTest.authenticate(request);
@Test
public void does_not_authenticate_when_authorization_header_is_not_BASIC() {
- when(request.getHeader("Authorization")).thenReturn("OTHER " + CREDENTIALS_IN_BASE64);
+ when(request.getHeader(AUTHORIZATION_HEADER)).thenReturn("OTHER " + CREDENTIALS_IN_BASE64);
underTest.authenticate(request);
@Test
public void fail_to_authenticate_when_no_login() {
- when(request.getHeader("Authorization")).thenReturn("Basic " + toBase64(":" + A_PASSWORD));
+ when(request.getHeader(AUTHORIZATION_HEADER)).thenReturn("Basic " + toBase64(":" + A_PASSWORD));
assertThatThrownBy(() -> underTest.authenticate(request))
.isInstanceOf(AuthenticationException.class)
@Test
public void fail_to_authenticate_when_invalid_header() {
- when(request.getHeader("Authorization")).thenReturn("Basic Invà lid");
+ when(request.getHeader(AUTHORIZATION_HEADER)).thenReturn("Basic Invà lid");
assertThatThrownBy(() -> underTest.authenticate(request))
.hasMessage("Invalid basic header")
@Test
public void authenticate_from_user_token() {
UserDto user = db.users().insertUser();
- var result = new UserTokenAuthentication.UserTokenAuthenticationResult(user.getUuid(), "my-token");
- when(userTokenAuthentication.authenticate("token", EXAMPLE_ENDPOINT, null)).thenReturn(result);
- when(request.getHeader("Authorization")).thenReturn("Basic " + toBase64("token:"));
+ when(userTokenAuthentication.authenticate(request)).thenReturn(Optional.of(new UserAuthResult(user, new UserTokenDto().setName("my-token"), UserAuthResult.AuthType.TOKEN)));
+ when(request.getHeader(AUTHORIZATION_HEADER)).thenReturn("Basic " + toBase64("token:"));
Optional<UserDto> userAuthenticated = underTest.authenticate(request);
assertThat(userAuthenticated).isPresent();
assertThat(userAuthenticated.get().getLogin()).isEqualTo(user.getLogin());
- verify(authenticationEvent).loginSuccess(request, user.getLogin(), Source.local(BASIC_TOKEN));
- verify(request).setAttribute("TOKEN_NAME", "my-token");
}
@Test
public void does_not_authenticate_from_user_token_when_token_is_invalid() {
- var result = new UserTokenAuthentication.UserTokenAuthenticationResult("Token doesn't exist");
- when(userTokenAuthentication.authenticate("token", EXAMPLE_ENDPOINT, null)).thenReturn(result);
- when(request.getHeader("Authorization")).thenReturn("Basic " + toBase64("token:"));
+ when(userTokenAuthentication.authenticate(request)).thenReturn(Optional.empty());
+ when(request.getHeader(AUTHORIZATION_HEADER)).thenReturn("Basic " + toBase64("token:"));
assertThatThrownBy(() -> underTest.authenticate(request))
- .hasMessage("Token doesn't exist")
+ .hasMessage("User doesn't exist")
.isInstanceOf(AuthenticationException.class)
.hasFieldOrPropertyWithValue("source", Source.local(BASIC_TOKEN));
@Test
public void does_not_authenticate_from_user_token_when_token_does_not_match_existing_user() {
- var result = new UserTokenAuthentication.UserTokenAuthenticationResult("unknown-user-uuid", "my-token");
- when(userTokenAuthentication.authenticate("token", EXAMPLE_ENDPOINT, null)).thenReturn(result);
- when(request.getHeader("Authorization")).thenReturn("Basic " + toBase64("token:"));
-
- assertThatThrownBy(() -> underTest.authenticate(request))
- .hasMessageContaining("User doesn't exist")
- .isInstanceOf(AuthenticationException.class)
- .hasFieldOrPropertyWithValue("source", Source.local(BASIC_TOKEN));
-
- verifyNoInteractions(authenticationEvent);
- }
-
- @Test
- public void does_not_authenticate_from_user_token_when_token_does_not_match_active_user() {
- UserDto user = db.users().insertDisabledUser();
- var result = new UserTokenAuthentication.UserTokenAuthenticationResult(user.getUuid(), "my-token");
- when(userTokenAuthentication.authenticate("token", EXAMPLE_ENDPOINT, null)).thenReturn(result);
- when(request.getHeader("Authorization")).thenReturn("Basic " + toBase64("token:"));
+ when(userTokenAuthentication.authenticate(request)).thenThrow(AuthenticationException.newBuilder()
+ .setSource(AuthenticationEvent.Source.local(AuthenticationEvent.Method.BASIC_TOKEN))
+ .setMessage("User doesn't exist")
+ .build());
+ when(request.getHeader(AUTHORIZATION_HEADER)).thenReturn("Basic " + toBase64("token:"));
assertThatThrownBy(() -> underTest.authenticate(request))
.hasMessageContaining("User doesn't exist")
import org.junit.Before;
import org.junit.Test;
import org.sonar.db.user.UserDto;
+import org.sonar.db.user.UserTokenDto;
import org.sonar.server.authentication.event.AuthenticationEvent;
import org.sonar.server.authentication.event.AuthenticationException;
import org.sonar.server.tester.AnonymousMockUserSession;
import org.sonar.server.tester.MockUserSession;
import org.sonar.server.user.UserSession;
import org.sonar.server.user.UserSessionFactory;
+import org.sonar.server.usertoken.UserTokenAuthentication;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import static org.sonar.db.user.TokenType.USER_TOKEN;
import static org.sonar.db.user.UserTesting.newUserDto;
public class RequestAuthenticatorImplTest {
private static final UserDto A_USER = newUserDto();
-
- private HttpServletRequest request = mock(HttpServletRequest.class);
- private HttpServletResponse response = mock(HttpServletResponse.class);
- private JwtHttpHandler jwtHttpHandler = mock(JwtHttpHandler.class);
- private BasicAuthentication basicAuthentication = mock(BasicAuthentication.class);
- private HttpHeadersAuthentication httpHeadersAuthentication = mock(HttpHeadersAuthentication.class);
- private UserSessionFactory sessionFactory = mock(UserSessionFactory.class);
- private CustomAuthentication customAuthentication1 = mock(CustomAuthentication.class);
- private CustomAuthentication customAuthentication2 = mock(CustomAuthentication.class);
- private RequestAuthenticator underTest = new RequestAuthenticatorImpl(jwtHttpHandler, basicAuthentication, httpHeadersAuthentication, sessionFactory,
+ private static final UserTokenDto A_USER_TOKEN = mockUserTokenDto(A_USER);
+
+ private final HttpServletRequest request = mock(HttpServletRequest.class);
+ private final HttpServletResponse response = mock(HttpServletResponse.class);
+ private final JwtHttpHandler jwtHttpHandler = mock(JwtHttpHandler.class);
+ private final BasicAuthentication basicAuthentication = mock(BasicAuthentication.class);
+ private final UserTokenAuthentication userTokenAuthentication = mock(UserTokenAuthentication.class);
+ private final HttpHeadersAuthentication httpHeadersAuthentication = mock(HttpHeadersAuthentication.class);
+ private final UserSessionFactory sessionFactory = mock(UserSessionFactory.class);
+ private final CustomAuthentication customAuthentication1 = mock(CustomAuthentication.class);
+ private final CustomAuthentication customAuthentication2 = mock(CustomAuthentication.class);
+ private final RequestAuthenticator underTest = new RequestAuthenticatorImpl(jwtHttpHandler, basicAuthentication, userTokenAuthentication, httpHeadersAuthentication, sessionFactory,
new CustomAuthentication[]{customAuthentication1, customAuthentication2});
@Before
public void setUp() {
when(sessionFactory.create(A_USER)).thenReturn(new MockUserSession(A_USER));
+ when(sessionFactory.create(A_USER, A_USER_TOKEN)).thenReturn(new MockUserSession(A_USER));
when(sessionFactory.createAnonymous()).thenReturn(new AnonymousMockUserSession());
}
verify(response, never()).setStatus(anyInt());
}
+ @Test
+ public void authenticate_from_basic_token() {
+ when(request.getHeader("Authorization")).thenReturn("Basic dGVzdDo=");
+ when(userTokenAuthentication.getUserToken("test")).thenReturn(A_USER_TOKEN);
+ when(userTokenAuthentication.authenticate(request)).thenReturn(Optional.of(new UserAuthResult(A_USER, A_USER_TOKEN, UserAuthResult.AuthType.TOKEN)));
+ when(httpHeadersAuthentication.authenticate(request, response)).thenReturn(Optional.empty());
+ when(jwtHttpHandler.validateToken(request, response)).thenReturn(Optional.empty());
+
+ assertThat(underTest.authenticate(request, response).getUuid()).isEqualTo(A_USER.getUuid());
+
+ verify(jwtHttpHandler).validateToken(request, response);
+ verify(userTokenAuthentication).authenticate(request);
+ verify(response, never()).setStatus(anyInt());
+ }
+
@Test
public void authenticate_from_sso() {
when(httpHeadersAuthentication.authenticate(request, response)).thenReturn(Optional.of(A_USER));
assertThat(session.getLogin()).isEqualTo("foo");
}
+
+ private static UserTokenDto mockUserTokenDto(UserDto userDto) {
+ UserTokenDto userTokenDto = new UserTokenDto();
+ userTokenDto.setType(USER_TOKEN.name());
+ userTokenDto.setName("User Token");
+ userTokenDto.setUserUuid(userDto.getUuid());
+ return userTokenDto;
+ }
+
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 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.user;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbTester;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.db.permission.GlobalPermission;
+import org.sonar.db.user.UserDto;
+import org.sonar.db.user.UserTokenDto;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.api.web.UserRole.SCAN;
+import static org.sonar.db.user.TokenType.GLOBAL_ANALYSIS_TOKEN;
+import static org.sonar.db.user.TokenType.PROJECT_ANALYSIS_TOKEN;
+import static org.sonar.db.user.TokenType.USER_TOKEN;
+
+public class TokenUserSessionTest {
+
+ @Rule
+ public final DbTester db = DbTester.create(System2.INSTANCE);
+ private final DbClient dbClient = db.getDbClient();
+
+ @Test
+ public void test_hasProjectsPermission_for_UserToken() {
+ ComponentDto project1 = db.components().insertPrivateProject();
+ ComponentDto project2 = db.components().insertPrivateProject();
+
+ UserDto user = db.users().insertUser();
+
+ db.users().insertProjectPermissionOnUser(user, SCAN, project1);
+
+ TokenUserSession userSession = mockTokenUserSession(user);
+
+ assertThat(userSession.hasProjectUuidPermission(SCAN, project1.projectUuid())).isTrue();
+ assertThat(userSession.hasProjectUuidPermission(SCAN, project2.projectUuid())).isFalse();
+ }
+
+ @Test
+ public void test_hasProjectsPermission_for_ProjecAnalysisToken() {
+ ComponentDto project1 = db.components().insertPrivateProject();
+ ComponentDto project2 = db.components().insertPrivateProject();
+
+ UserDto user = db.users().insertUser();
+
+ db.users().insertProjectPermissionOnUser(user, SCAN, project1);
+ db.users().insertProjectPermissionOnUser(user, SCAN, project2);
+
+ TokenUserSession userSession = mockProjectAnalysisTokenUserSession(user,project1);
+
+ assertThat(userSession.hasProjectUuidPermission(SCAN, project1.projectUuid())).isTrue();
+ assertThat(userSession.hasProjectUuidPermission(SCAN, project2.projectUuid())).isFalse();
+ }
+
+ @Test
+ public void test_hasProjectsPermission_for_ProjectAnalysisToken_with_global_permission() {
+ ComponentDto project1 = db.components().insertPrivateProject();
+ ComponentDto project2 = db.components().insertPrivateProject();
+
+ UserDto user = db.users().insertUser();
+
+ db.users().insertPermissionOnUser(user, GlobalPermission.SCAN);
+
+ TokenUserSession userSession = mockProjectAnalysisTokenUserSession(user,project1);
+
+ assertThat(userSession.hasProjectUuidPermission(SCAN, project1.projectUuid())).isTrue();
+ assertThat(userSession.hasProjectUuidPermission(SCAN, project2.projectUuid())).isFalse();
+ }
+
+ @Test
+ public void test_hasGlobalPermission_for_UserToken() {
+ UserDto user = db.users().insertUser();
+ db.users().insertPermissionOnUser(user, GlobalPermission.SCAN);
+
+ TokenUserSession userSession = mockTokenUserSession(user);
+
+ assertThat(userSession.hasPermission(GlobalPermission.SCAN)).isTrue();
+ }
+
+ @Test
+ public void test_hasGlobalPermission_for_ProjecAnalysisToken() {
+ ComponentDto project1 = db.components().insertPrivateProject();
+ ComponentDto project2 = db.components().insertPrivateProject();
+
+ UserDto user = db.users().insertUser();
+
+ db.users().insertProjectPermissionOnUser(user, SCAN, project1);
+ db.users().insertProjectPermissionOnUser(user, SCAN, project2);
+
+ db.users().insertPermissionOnUser(user, GlobalPermission.SCAN);
+
+ TokenUserSession userSession = mockProjectAnalysisTokenUserSession(user,project1);
+
+ assertThat(userSession.hasPermission(GlobalPermission.SCAN)).isFalse();
+ }
+
+ @Test
+ public void test_hasGlobalPermission_for_GlobalAnalysisToken() {
+ ComponentDto project1 = db.components().insertPrivateProject();
+
+ UserDto user = db.users().insertUser();
+
+ db.users().insertPermissionOnUser(user, GlobalPermission.SCAN);
+
+ TokenUserSession userSession = mockGlobalAnalysisTokenUserSession(user);
+
+ assertThat(userSession.hasProjectUuidPermission(SCAN, project1.projectUuid())).isFalse();
+ assertThat(userSession.hasPermission(GlobalPermission.SCAN)).isTrue();
+ }
+
+ private TokenUserSession mockTokenUserSession(UserDto userDto) {
+ return new TokenUserSession(dbClient, userDto, mockUserTokenDto());
+ }
+
+ private TokenUserSession mockProjectAnalysisTokenUserSession(UserDto userDto, ComponentDto componentDto) {
+ return new TokenUserSession(dbClient, userDto, mockProjectAnalysisTokenDto(componentDto));
+ }
+
+ private TokenUserSession mockGlobalAnalysisTokenUserSession(UserDto userDto) {
+ return new TokenUserSession(dbClient, userDto, mockGlobalAnalysisTokenDto());
+ }
+
+ private UserTokenDto mockUserTokenDto() {
+ UserTokenDto userTokenDto = new UserTokenDto();
+ userTokenDto.setType(USER_TOKEN.name());
+ userTokenDto.setName("User Token");
+ userTokenDto.setUserUuid("userUid");
+ return userTokenDto;
+ }
+
+ private UserTokenDto mockProjectAnalysisTokenDto(ComponentDto componentDto) {
+ UserTokenDto userTokenDto = new UserTokenDto();
+ userTokenDto.setType(PROJECT_ANALYSIS_TOKEN.name());
+ userTokenDto.setName("Project Analysis Token");
+ userTokenDto.setUserUuid("userUid");
+ userTokenDto.setProjectKey(componentDto.getKey());
+ userTokenDto.setProjectName(componentDto.name());
+ userTokenDto.setProjectUuid(componentDto.projectUuid());
+ return userTokenDto;
+ }
+
+ private UserTokenDto mockGlobalAnalysisTokenDto() {
+ UserTokenDto userTokenDto = new UserTokenDto();
+ userTokenDto.setType(GLOBAL_ANALYSIS_TOKEN.name());
+ userTokenDto.setName("Global Analysis Token");
+ userTokenDto.setUserUuid("userUid");
+ return userTokenDto;
+ }
+
+}
*/
package org.sonar.server.usertoken;
+import java.util.Base64;
+import java.util.Optional;
+import javax.servlet.http.HttpServletRequest;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.api.utils.System2;
import org.sonar.db.DbTester;
-import org.sonar.db.user.TokenType;
import org.sonar.db.user.UserDto;
import org.sonar.db.user.UserTokenDto;
+import org.sonar.server.authentication.UserAuthResult;
import org.sonar.server.authentication.UserLastConnectionDatesUpdater;
-import org.sonar.server.usertoken.UserTokenAuthentication.UserTokenAuthenticationResult;
+import org.sonar.server.authentication.event.AuthenticationEvent;
+import org.sonar.server.authentication.event.AuthenticationException;
+import static java.nio.charset.StandardCharsets.UTF_8;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;
+import static org.sonar.db.user.TokenType.GLOBAL_ANALYSIS_TOKEN;
+import static org.sonar.db.user.TokenType.PROJECT_ANALYSIS_TOKEN;
+import static org.sonar.db.user.TokenType.USER_TOKEN;
+import static org.sonar.server.authentication.event.AuthenticationEvent.Method.BASIC_TOKEN;
+import static org.sonar.server.usertoken.UserTokenAuthentication.isTokenBasedAuthentication;
public class UserTokenAuthenticationTest {
- private static final String EXAMPLE_SCANNER_ENDPOINT = "/api/settings/values.protobuf";
- private static final String EXAMPLE_USER_ENDPOINT = "/api/editions/set_license";
+ private static final Base64.Encoder BASE64_ENCODER = Base64.getEncoder();
- private static final String EXAMPLE_PROJECT_KEY = "my-project-key";
+ private static final String AUTHORIZATION_HEADER = "Authorization";
private static final String EXAMPLE_OLD_USER_TOKEN = "StringWith40CharactersThatIsOldUserToken";
private static final String EXAMPLE_NEW_USER_TOKEN = "squ_StringWith44CharactersThatIsNewUserToken";
@Rule
public DbTester db = DbTester.create(System2.INSTANCE);
- private TokenGenerator tokenGenerator = mock(TokenGenerator.class);
- private UserLastConnectionDatesUpdater userLastConnectionDatesUpdater = mock(UserLastConnectionDatesUpdater.class);
-
- private UserTokenAuthentication underTest = new UserTokenAuthentication(tokenGenerator, db.getDbClient(), userLastConnectionDatesUpdater);
+ private final TokenGenerator tokenGenerator = mock(TokenGenerator.class);
+ private final UserLastConnectionDatesUpdater userLastConnectionDatesUpdater = mock(UserLastConnectionDatesUpdater.class);
+ private final AuthenticationEvent authenticationEvent = mock(AuthenticationEvent.class);
+ private final HttpServletRequest request = mock(HttpServletRequest.class);
+ private final UserTokenAuthentication underTest = new UserTokenAuthentication(tokenGenerator, db.getDbClient(), userLastConnectionDatesUpdater, authenticationEvent);
@Before
public void before() {
+ when(request.getHeader(AUTHORIZATION_HEADER)).thenReturn("Basic " + toBase64("token:"));
when(tokenGenerator.hash(EXAMPLE_OLD_USER_TOKEN)).thenReturn(OLD_USER_TOKEN_HASH);
when(tokenGenerator.hash(EXAMPLE_NEW_USER_TOKEN)).thenReturn(NEW_USER_TOKEN_HASH);
when(tokenGenerator.hash(EXAMPLE_PROJECT_ANALYSIS_TOKEN)).thenReturn(PROJECT_ANALYSIS_TOKEN_HASH);
public void return_login_when_token_hash_found_in_db() {
String token = "known-token";
String tokenHash = "123456789";
+ when(request.getHeader(AUTHORIZATION_HEADER)).thenReturn("Basic " + toBase64(token + ":"));
when(tokenGenerator.hash(token)).thenReturn(tokenHash);
UserDto user1 = db.users().insertUser();
- db.users().insertToken(user1, t -> t.setTokenHash(tokenHash));
+ UserTokenDto userTokenDto = db.users().insertToken(user1, t -> t.setTokenHash(tokenHash));
UserDto user2 = db.users().insertUser();
db.users().insertToken(user2, t -> t.setTokenHash("another-token-hash"));
- UserTokenAuthenticationResult result = underTest.authenticate(token, EXAMPLE_USER_ENDPOINT, null);
+ Optional<UserAuthResult> result = underTest.authenticate(request);
- assertThat(result.getAuthenticatedUserUuid())
+ assertThat(result).isPresent();
+ assertThat(result.get().getTokenDto().getUuid()).isEqualTo(userTokenDto.getUuid());
+ assertThat(result.get().getUserDto().getUuid())
.isNotNull()
.contains(user1.getUuid());
verify(userLastConnectionDatesUpdater).updateLastConnectionDateIfNeeded(any(UserTokenDto.class));
}
+ @Test
+ public void return_absent_if_username_password_used() {
+ when(request.getHeader(AUTHORIZATION_HEADER)).thenReturn("Basic " + toBase64("login:password"));
+
+ Optional<UserAuthResult> result = underTest.authenticate(request);
+
+ assertThat(result).isEmpty();
+ verify(userLastConnectionDatesUpdater, never()).updateLastConnectionDateIfNeeded(any(UserTokenDto.class));
+ verifyNoInteractions(authenticationEvent);
+ }
+
@Test
public void return_absent_if_token_hash_is_not_found() {
- var result = underTest.authenticate(EXAMPLE_OLD_USER_TOKEN, EXAMPLE_USER_ENDPOINT, null);
+ when(request.getHeader(AUTHORIZATION_HEADER)).thenReturn("Basic " + toBase64(EXAMPLE_OLD_USER_TOKEN + ":"));
- assertThat(result.getAuthenticatedUserUuid()).isNull();
+ assertThatThrownBy(() -> underTest.authenticate(request))
+ .hasMessageContaining("Token doesn't exist")
+ .isInstanceOf(AuthenticationException.class);
verify(userLastConnectionDatesUpdater, never()).updateLastConnectionDateIfNeeded(any(UserTokenDto.class));
+ verifyNoInteractions(authenticationEvent);
}
@Test
- public void authenticate_givenProjectTokenAndUserEndpoint_fillErrorMessage() {
+ public void authenticate_givenGlobalToken_resultContainsUuid() {
UserDto user = db.users().insertUser();
- db.users().insertToken(user, t -> t.setTokenHash(PROJECT_ANALYSIS_TOKEN_HASH).setType(TokenType.PROJECT_ANALYSIS_TOKEN.name()));
+ String tokenName = db.users().insertToken(user, t -> t.setTokenHash(GLOBAL_ANALYSIS_TOKEN_HASH).setType(GLOBAL_ANALYSIS_TOKEN.name())).getName();
- var authenticate = underTest.authenticate(EXAMPLE_PROJECT_ANALYSIS_TOKEN, EXAMPLE_USER_ENDPOINT, EXAMPLE_PROJECT_KEY);
+ when(request.getHeader(AUTHORIZATION_HEADER)).thenReturn("Basic " + toBase64(EXAMPLE_GLOBAL_ANALYSIS_TOKEN + ":"));
+ var result = underTest.authenticate(request);
- assertThat(authenticate.getErrorMessage()).isNotNull().contains("Invalid token");
+ assertThat(result).isPresent();
+ assertThat(result.get().getTokenDto().getUuid()).isNotNull();
+ assertThat(result.get().getTokenDto().getType()).isEqualTo(GLOBAL_ANALYSIS_TOKEN.name());
+ verify(authenticationEvent).loginSuccess(request, user.getLogin(), AuthenticationEvent.Source.local(BASIC_TOKEN));
+ verify(request).setAttribute("TOKEN_NAME",tokenName);
}
@Test
- public void authenticate_givenProjectTokenAndUserEndpoint_InvalidTokenErrorMessage() {
+ public void authenticate_givenNewUserToken_resultContainsUuid() {
UserDto user = db.users().insertUser();
- db.users().insertToken(user, t -> t.setTokenHash(PROJECT_ANALYSIS_TOKEN_HASH).setType(TokenType.PROJECT_ANALYSIS_TOKEN.name()));
+ String tokenName = db.users().insertToken(user, t -> t.setTokenHash(NEW_USER_TOKEN_HASH).setType(USER_TOKEN.name())).getName();
- var result = underTest.authenticate(EXAMPLE_PROJECT_ANALYSIS_TOKEN, EXAMPLE_USER_ENDPOINT, EXAMPLE_PROJECT_KEY);
+ when(request.getHeader(AUTHORIZATION_HEADER)).thenReturn("Basic " + toBase64(EXAMPLE_NEW_USER_TOKEN + ":"));
+ var result = underTest.authenticate(request);
- assertThat(result.getErrorMessage()).isNotNull().contains("Invalid token");
+ assertThat(result).isPresent();
+ assertThat(result.get().getTokenDto().getUuid()).isNotNull();
+ assertThat(result.get().getTokenDto().getType()).isEqualTo(USER_TOKEN.name());
+ verify(authenticationEvent).loginSuccess(request, user.getLogin(), AuthenticationEvent.Source.local(BASIC_TOKEN));
+ verify(request).setAttribute("TOKEN_NAME",tokenName);
}
@Test
- public void authenticate_givenGlobalTokenAndScannerEndpoint_resultContainsUuid() {
+ public void authenticate_givenProjectToken_resultContainsUuid() {
UserDto user = db.users().insertUser();
- db.users().insertToken(user, t -> t.setTokenHash(GLOBAL_ANALYSIS_TOKEN_HASH).setType(TokenType.GLOBAL_ANALYSIS_TOKEN.name()));
+ String tokenName = db.users().insertToken(user, t -> t.setTokenHash(PROJECT_ANALYSIS_TOKEN_HASH)
+ .setProjectKey("project-key")
+ .setType(PROJECT_ANALYSIS_TOKEN.name())).getName();
- var result = underTest.authenticate(EXAMPLE_GLOBAL_ANALYSIS_TOKEN, EXAMPLE_SCANNER_ENDPOINT, EXAMPLE_PROJECT_KEY);
+ when(request.getHeader(AUTHORIZATION_HEADER)).thenReturn("Basic " + toBase64(EXAMPLE_PROJECT_ANALYSIS_TOKEN + ":"));
+ var result = underTest.authenticate(request);
- assertThat(result.getAuthenticatedUserUuid()).isNotNull();
- assertThat(result.getErrorMessage()).isNull();
+ assertThat(result).isPresent();
+ assertThat(result.get().getTokenDto().getUuid()).isNotNull();
+ assertThat(result.get().getTokenDto().getType()).isEqualTo(PROJECT_ANALYSIS_TOKEN.name());
+ assertThat(result.get().getTokenDto().getProjectKey()).isEqualTo("project-key");
+ verify(authenticationEvent).loginSuccess(request, user.getLogin(), AuthenticationEvent.Source.local(BASIC_TOKEN));
+ verify(request).setAttribute("TOKEN_NAME",tokenName);
}
+
@Test
- public void authenticate_givenNewUserTokenAndScannerEndpoint_resultContainsUuid() {
- UserDto user = db.users().insertUser();
- db.users().insertToken(user, t -> t.setTokenHash(NEW_USER_TOKEN_HASH).setType(TokenType.USER_TOKEN.name()));
+ public void does_not_authenticate_from_user_token_when_token_does_not_match_active_user() {
+ UserDto user = db.users().insertDisabledUser();
+ String tokenName = db.users().insertToken(user, t -> t.setTokenHash(NEW_USER_TOKEN_HASH).setType(USER_TOKEN.name())).getName();
+
+ when(request.getHeader(AUTHORIZATION_HEADER)).thenReturn("Basic " + toBase64(EXAMPLE_NEW_USER_TOKEN + ":"));
- var result = underTest.authenticate(EXAMPLE_NEW_USER_TOKEN, EXAMPLE_SCANNER_ENDPOINT, null);
+ assertThatThrownBy(() -> underTest.authenticate(request))
+ .hasMessageContaining("User doesn't exist")
+ .isInstanceOf(AuthenticationException.class)
+ .hasFieldOrPropertyWithValue("source", AuthenticationEvent.Source.local(BASIC_TOKEN));
- assertThat(result.getAuthenticatedUserUuid()).isNotNull();
- assertThat(result.getErrorMessage()).isNull();
+ verifyNoInteractions(authenticationEvent);
}
@Test
- public void authenticate_givenProjectTokenAndScannerEndpointAndValidProjectKey_resultContainsUuid() {
- UserDto user = db.users().insertUser();
- db.users().insertToken(user, t -> t.setTokenHash(PROJECT_ANALYSIS_TOKEN_HASH)
- .setProjectKey("project-key")
- .setType(TokenType.PROJECT_ANALYSIS_TOKEN.name()));
+ public void return_token_from_db() {
+ String token = "known-token";
+ String tokenHash = "123456789";
+ when(tokenGenerator.hash(token)).thenReturn(tokenHash);
+ UserDto user1 = db.users().insertUser();
+ UserTokenDto userTokenDto = db.users().insertToken(user1, t -> t.setTokenHash(tokenHash));
- var result = underTest.authenticate(EXAMPLE_PROJECT_ANALYSIS_TOKEN, EXAMPLE_SCANNER_ENDPOINT, "project-key");
+ UserTokenDto result = underTest.getUserToken(token);
- assertThat(result.getAuthenticatedUserUuid()).isNotNull();
- assertThat(result.getErrorMessage()).isNull();
+ assertThat(result.getUuid()).isEqualTo(userTokenDto.getUuid());
}
@Test
- public void authenticate_givenProjectTokenAndScannerEndpointAndWrongProjectKey_resultContainsErrorMessage() {
- UserDto user = db.users().insertUser();
- db.users().insertToken(user, t -> t.setTokenHash(PROJECT_ANALYSIS_TOKEN_HASH)
- .setProjectKey("project-key")
- .setType(TokenType.PROJECT_ANALYSIS_TOKEN.name()));
+ public void identifies_if_request_uses_token_based_authentication() {
+ when(request.getHeader(AUTHORIZATION_HEADER)).thenReturn("Basic " + toBase64("token:"));
+ assertThat(isTokenBasedAuthentication(request)).isTrue();
- var result = underTest.authenticate(EXAMPLE_PROJECT_ANALYSIS_TOKEN, EXAMPLE_SCANNER_ENDPOINT, "project-key-2");
+ when(request.getHeader(AUTHORIZATION_HEADER)).thenReturn("Basic " + toBase64("login:password"));
+ assertThat(isTokenBasedAuthentication(request)).isFalse();
+
+ when(request.getHeader(AUTHORIZATION_HEADER)).thenReturn(null);
+ assertThat(isTokenBasedAuthentication(request)).isFalse();
+ }
- assertThat(result.getAuthenticatedUserUuid()).isNull();
- assertThat(result.getErrorMessage()).isNotNull();
+ private static String toBase64(String text) {
+ return new String(BASE64_ENCODER.encode(text.getBytes(UTF_8)));
}
}
import org.sonar.db.permission.GlobalPermission;
import org.sonar.db.user.GroupDto;
import org.sonar.db.user.UserDto;
+import org.sonar.db.user.UserTokenDto;
import static java.util.Objects.requireNonNull;
return new TestUserSession(requireNonNull(user));
}
+ @Override
+ public UserSession create(UserDto user, UserTokenDto userToken) {
+ return new TestUserSession(requireNonNull(user));
+ }
+
@Override
public UserSession createAnonymous() {
return new TestUserSession(null);
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.api.utils.log.Profiler;
-import org.sonarqube.ws.client.GetRequest;
import org.sonarqube.ws.client.HttpException;
-import org.sonarqube.ws.client.PostRequest;
import org.sonarqube.ws.client.WsClient;
import org.sonarqube.ws.client.WsConnector;
import org.sonarqube.ws.client.WsRequest;
private static final int MAX_ERROR_MSG_LEN = 128;
private static final Logger LOG = Loggers.get(DefaultScannerWsClient.class);
- private static final String PROJECT_KEY_CONTEXT_HEADER = "PROJECT_KEY";
-
private final WsClient target;
private final boolean hasCredentials;
private final GlobalAnalysisMode globalMode;
- private final ScannerProperties scannerProperties;
- public DefaultScannerWsClient(WsClient target, boolean hasCredentials, GlobalAnalysisMode globalMode, ScannerProperties scannerProperties) {
+ public DefaultScannerWsClient(WsClient target, boolean hasCredentials, GlobalAnalysisMode globalMode) {
this.target = target;
this.hasCredentials = hasCredentials;
this.globalMode = globalMode;
- this.scannerProperties = scannerProperties;
}
/**
* @throws MessageException if there was a problem with authentication or if a error message was parsed from the response.
* @throws HttpException if the response code is not in range [200..300). Consider using {@link #createErrorMessage(HttpException)} to create more relevant messages for the users.
*/
- private WsResponse getResponse(WsRequest request) {
+ public WsResponse call(WsRequest request) {
checkState(!globalMode.isMediumTest(), "No WS call should be made in medium test mode");
Profiler profiler = Profiler.createIfDebug(LOG).start();
WsResponse response = target.wsConnector().call(request);
return response;
}
- public WsResponse call(GetRequest getRequest) {
- getRequest.setHeader(PROJECT_KEY_CONTEXT_HEADER, scannerProperties.getProjectKey());
- return getResponse(getRequest);
- }
-
- public WsResponse call(PostRequest postRequest) {
- postRequest.setHeader(PROJECT_KEY_CONTEXT_HEADER, scannerProperties.getProjectKey());
- return getResponse(postRequest);
- }
-
public String baseUrl() {
return target.wsConnector().baseUrl();
}
*/
package org.sonar.scanner.bootstrap;
-import org.sonarqube.ws.client.GetRequest;
-import org.sonarqube.ws.client.PostRequest;
+import org.sonarqube.ws.client.WsRequest;
import org.sonarqube.ws.client.WsResponse;
public interface ScannerWsClient {
- WsResponse call(GetRequest request);
-
- WsResponse call(PostRequest request);
+ WsResponse call(WsRequest request);
String baseUrl();
-
}
}
return new DefaultScannerWsClient(WsClientFactories.getDefault().newClient(connectorBuilder.build()), login != null,
- globalMode, scannerProps);
+ globalMode);
}
}
import org.apache.commons.lang.StringUtils;
import org.mockito.ArgumentMatcher;
import org.sonar.scanner.bootstrap.DefaultScannerWsClient;
-import org.sonarqube.ws.client.GetRequest;
import org.sonarqube.ws.client.WsRequest;
import org.sonarqube.ws.client.WsResponse;
public static void mockStream(DefaultScannerWsClient mock, String path, InputStream is) {
WsResponse response = mock(WsResponse.class);
when(response.contentStream()).thenReturn(is);
- when(mock.call((GetRequest) argThat(new RequestMatcher(path)))).thenReturn(response);
+ when(mock.call(argThat(new RequestMatcher(path)))).thenReturn(response);
}
public static void mockStream(DefaultScannerWsClient mock, InputStream is) {
WsResponse response = mock(WsResponse.class);
when(response.contentStream()).thenReturn(is);
- when(mock.call(any(GetRequest.class))).thenReturn(response);
+ when(mock.call(any(WsRequest.class))).thenReturn(response);
}
public static void mockReader(DefaultScannerWsClient mock, Reader reader) {
WsResponse response = mock(WsResponse.class);
when(response.contentReader()).thenReturn(reader);
- when(mock.call(any(GetRequest.class))).thenReturn(response);
+ when(mock.call(any(WsRequest.class))).thenReturn(response);
}
public static void mockReader(DefaultScannerWsClient mock, String path, Reader reader, Reader... others) {
otherResponses[i] = otherResponse;
}
- when(mock.call((GetRequest) argThat(new RequestMatcher(path)))).thenReturn(response, otherResponses);
+ when(mock.call(argThat(new RequestMatcher(path)))).thenReturn(response, otherResponses);
}
public static void mockException(DefaultScannerWsClient mock, Exception e) {
- when(mock.call(any(GetRequest.class))).thenThrow(e);
+ when(mock.call(any(WsRequest.class))).thenThrow(e);
}
public static void mockException(DefaultScannerWsClient mock, String path, Exception e) {
- when(mock.call((GetRequest) argThat(new RequestMatcher(path)))).thenThrow(e);
+ when(mock.call(argThat(new RequestMatcher(path)))).thenThrow(e);
}
public static void verifyCall(DefaultScannerWsClient mock, String path) {
- verify(mock).call((GetRequest) argThat(new RequestMatcher(path)));
+ verify(mock).call(argThat(new RequestMatcher(path)));
}
private static class RequestMatcher implements ArgumentMatcher<WsRequest> {
*/
package org.sonar.scanner.bootstrap;
+import java.util.Collections;
import java.util.List;
import org.apache.commons.lang.StringUtils;
-import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mockito;
import org.sonarqube.ws.client.GetRequest;
import org.sonarqube.ws.client.HttpException;
import org.sonarqube.ws.client.MockWsResponse;
-import org.sonarqube.ws.client.PostRequest;
import org.sonarqube.ws.client.WsClient;
+import org.sonarqube.ws.client.WsRequest;
import org.sonarqube.ws.client.WsResponse;
import static org.assertj.core.api.Assertions.assertThat;
private final WsClient wsClient = mock(WsClient.class, Mockito.RETURNS_DEEP_STUBS);
- private final ScannerProperties scannerProperties = mock(ScannerProperties.class);
-
- @Before
- public void before() {
- when(scannerProperties.getProjectKey()).thenReturn("projectKey");
- }
-
@Test
public void log_and_profile_request_if_debug_level() {
- GetRequest request = newGetRequest();
+ WsRequest request = newRequest();
WsResponse response = newResponse().setRequestUrl("https://local/api/issues/search");
when(wsClient.wsConnector().call(request)).thenReturn(response);
logTester.setLevel(LoggerLevel.DEBUG);
- DefaultScannerWsClient underTest = new DefaultScannerWsClient(wsClient, false, new GlobalAnalysisMode(scannerProperties),
- scannerProperties);
+ DefaultScannerWsClient underTest = new DefaultScannerWsClient(wsClient, false, new GlobalAnalysisMode(new ScannerProperties(Collections.emptyMap())));
WsResponse result = underTest.call(request);
assertThat(debugLogs.get(0)).contains("GET 200 https://local/api/issues/search | time=");
}
- @Test
- public void call_alwaysAddContextHeaders() {
- GetRequest getRequest = newGetRequest();
- PostRequest postRequest = newPostRequest();
-
- DefaultScannerWsClient underTest = new DefaultScannerWsClient(wsClient, false, new GlobalAnalysisMode(scannerProperties),
- scannerProperties);
-
- underTest.call(getRequest);
- underTest.call(postRequest);
-
- assertThat(getRequest.getHeaders().getValue("PROJECT_KEY")).contains("projectKey");
- assertThat(postRequest.getHeaders().getValue("PROJECT_KEY")).contains("projectKey");
- }
-
@Test
public void create_error_msg_from_json() {
String content = "{\"errors\":[{\"msg\":\"missing scan permission\"}, {\"msg\":\"missing another permission\"}]}";
@Test
public void fail_if_requires_credentials() {
- GetRequest request = newGetRequest();
+ WsRequest request = newRequest();
WsResponse response = newResponse().setCode(401);
when(wsClient.wsConnector().call(request)).thenReturn(response);
assertThatThrownBy(() -> new DefaultScannerWsClient(wsClient, false,
- new GlobalAnalysisMode(scannerProperties), scannerProperties).call(request))
+ new GlobalAnalysisMode(new ScannerProperties(Collections.emptyMap()))).call(request))
.isInstanceOf(MessageException.class)
.hasMessage("Not authorized. Analyzing this project requires authentication. Please provide a user token in sonar.login or other " +
"credentials in sonar.login and sonar.password.");
@Test
public void fail_if_credentials_are_not_valid() {
- GetRequest request = newGetRequest();
+ WsRequest request = newRequest();
WsResponse response = newResponse().setCode(401);
when(wsClient.wsConnector().call(request)).thenReturn(response);
assertThatThrownBy(() -> new DefaultScannerWsClient(wsClient, /* credentials are configured */true,
- new GlobalAnalysisMode(scannerProperties), scannerProperties).call(request))
+ new GlobalAnalysisMode(new ScannerProperties(Collections.emptyMap()))).call(request))
.isInstanceOf(MessageException.class)
.hasMessage("Not authorized. Please check the properties sonar.login and sonar.password.");
}
@Test
public void fail_if_requires_permission() {
- GetRequest request = newGetRequest();
+ WsRequest request = newRequest();
WsResponse response = newResponse()
.setCode(403);
when(wsClient.wsConnector().call(request)).thenReturn(response);
assertThatThrownBy(() -> new DefaultScannerWsClient(wsClient, true,
- new GlobalAnalysisMode(scannerProperties), scannerProperties).call(request))
+ new GlobalAnalysisMode(new ScannerProperties(Collections.emptyMap()))).call(request))
.isInstanceOf(MessageException.class)
.hasMessage("You're not authorized to run analysis. Please contact the project administrator.");
}
@Test
public void fail_if_bad_request() {
- GetRequest request = newGetRequest();
+ WsRequest request = newRequest();
WsResponse response = newResponse()
.setCode(400)
.setContent("{\"errors\":[{\"msg\":\"Boo! bad request! bad!\"}]}");
when(wsClient.wsConnector().call(request)).thenReturn(response);
assertThatThrownBy(() -> new DefaultScannerWsClient(wsClient, true,
- new GlobalAnalysisMode(scannerProperties), scannerProperties).call(request))
+ new GlobalAnalysisMode(new ScannerProperties(Collections.emptyMap()))).call(request))
.isInstanceOf(MessageException.class)
.hasMessage("Boo! bad request! bad!");
}
return new MockWsResponse().setRequestUrl("https://local/api/issues/search");
}
- private GetRequest newGetRequest() {
+ private WsRequest newRequest() {
return new GetRequest("api/issues/search");
}
-
- private PostRequest newPostRequest() {
- return new PostRequest("api/ce/task");
- }
}
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.fs.internal.DefaultInputProject;
import org.sonar.api.config.internal.MapSettings;
import org.sonar.scanner.bootstrap.ScannerPluginInstaller.InstalledPlugin;
import org.sonarqube.ws.client.HttpConnector;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.ThrowableAssert.ThrowingCallable;
-import static org.mockito.Mockito.mock;
public class PluginFilesTest {
HttpConnector connector = HttpConnector.newBuilder().url(server.url("/").toString()).build();
GlobalAnalysisMode analysisMode = new GlobalAnalysisMode(new ScannerProperties(Collections.emptyMap()));
DefaultScannerWsClient wsClient = new DefaultScannerWsClient(WsClientFactories.getDefault().newClient(connector), false,
- analysisMode, mock(ScannerProperties.class));
+ analysisMode);
userHome = temp.newFolder();
MapSettings settings = new MapSettings();
import org.sonar.scanner.bootstrap.DefaultScannerWsClient;
import org.sonar.scanner.protocol.internal.ScannerInternal.AnalysisCacheMsg;
import org.sonar.scanner.scan.branch.BranchConfiguration;
-import org.sonarqube.ws.client.GetRequest;
import org.sonarqube.ws.client.HttpException;
+import org.sonarqube.ws.client.WsRequest;
import org.sonarqube.ws.client.WsResponse;
import static org.assertj.core.api.Assertions.assertThat;
@Before
public void before() {
when(project.key()).thenReturn("myproject");
- when(wsClient.call(any(GetRequest.class))).thenReturn(response);
+ when(wsClient.call(any())).thenReturn(response);
}
@Test
@Test
public void returns_empty_if_404() {
- when(wsClient.call(any(GetRequest.class))).thenThrow(new HttpException("url", 404, "content"));
+ when(wsClient.call(any())).thenThrow(new HttpException("url", 404, "content"));
assertThat(loader.load()).isEmpty();
}
@Test
public void throw_error_if_http_exception_not_404() {
- when(wsClient.call(any(GetRequest.class))).thenThrow(new HttpException("url", 401, "content"));
+ when(wsClient.call(any())).thenThrow(new HttpException("url", 401, "content"));
assertThatThrownBy(loader::load)
.isInstanceOf(MessageException.class)
.hasMessage("Failed to download analysis cache: HTTP code 401: content");
}
private void assertRequestPath(String expectedPath) {
- ArgumentCaptor<GetRequest> requestCaptor = ArgumentCaptor.forClass(GetRequest.class);
+ ArgumentCaptor<WsRequest> requestCaptor = ArgumentCaptor.forClass(WsRequest.class);
verify(wsClient).call(requestCaptor.capture());
assertThat(requestCaptor.getValue().getPath()).isEqualTo(expectedPath);
}
import org.sonarqube.ws.Ce.TaskStatus;
import org.sonarqube.ws.Qualitygates;
import org.sonarqube.ws.Qualitygates.ProjectStatusResponse.Status;
-import org.sonarqube.ws.client.GetRequest;
import org.sonarqube.ws.client.HttpException;
import org.sonarqube.ws.client.MockWsResponse;
+import org.sonarqube.ws.client.WsRequest;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
.hasMessageContaining("CE Task finished abnormally with status: " + taskStatus.name());
}
- private GetRequest newGetCeTaskRequest() {
- return argThat(new GetRequestPathMatcher("api/ce/task"));
+ private WsRequest newGetCeTaskRequest() {
+ return argThat(new WsRequestPathMatcher("api/ce/task"));
}
private MockWsResponse getCeTaskWsResponse(TaskStatus status) {
.isInstanceOf(IllegalStateException.class);
}
- private GetRequest newGetQualityGateRequest() {
- return argThat(new GetRequestPathMatcher("api/qualitygates/project_status"));
+ private WsRequest newGetQualityGateRequest() {
+ return argThat(new WsRequestPathMatcher("api/qualitygates/project_status"));
}
private MockWsResponse getQualityGateWsResponse(Status status) {
};
}
- private static class GetRequestPathMatcher implements ArgumentMatcher<GetRequest> {
+ private static class WsRequestPathMatcher implements ArgumentMatcher<WsRequest> {
String path;
- GetRequestPathMatcher(String path) {
+ WsRequestPathMatcher(String path) {
this.path = path;
}
@Override
- public boolean matches(GetRequest right) {
+ public boolean matches(WsRequest right) {
return path.equals(right.getPath());
}
}
import org.sonarqube.ws.Ce;
import org.sonarqube.ws.client.HttpException;
import org.sonarqube.ws.client.MockWsResponse;
-import org.sonarqube.ws.client.PostRequest;
import org.sonarqube.ws.client.WsRequest;
import org.sonarqube.ws.client.WsResponse;
public void use_30s_write_timeout() {
MockWsResponse submitMockResponse = new MockWsResponse();
submitMockResponse.setContent(Ce.SubmitResponse.newBuilder().setTaskId("task-1234").build().toByteArray());
- when(wsClient.call(any(PostRequest.class))).thenReturn(submitMockResponse);
+ when(wsClient.call(any())).thenReturn(submitMockResponse);
underTest.start();
underTest.execute();
- verify(wsClient).call((PostRequest) argThat(req -> ((PostRequest) req).getWriteTimeOutInMs().orElse(0) == 30_000));
+ verify(wsClient).call(argThat(req -> (req).getWriteTimeOutInMs().orElse(0) == 30_000));
}
@Test
HttpException ex = new HttpException("url", 404, "{\"errors\":[{\"msg\":\"Organization with key 'MyOrg' does not exist\"}]}");
WsResponse response = mock(WsResponse.class);
when(response.failIfNotSuccessful()).thenThrow(ex);
- when(wsClient.call(any(PostRequest.class))).thenThrow(new IllegalStateException("timeout"));
+ when(wsClient.call(any(WsRequest.class))).thenThrow(new IllegalStateException("timeout"));
assertThatThrownBy(() -> underTest.upload(reportTempFolder.newFile()))
.isInstanceOf(IllegalStateException.class)
HttpException ex = new HttpException("url", 404, "{\"errors\":[{\"msg\":\"Organization with key 'MyOrg' does not exist\"}]}");
WsResponse response = mock(WsResponse.class);
when(response.failIfNotSuccessful()).thenThrow(ex);
- when(wsClient.call(any(PostRequest.class))).thenReturn(response);
+ when(wsClient.call(any(WsRequest.class))).thenReturn(response);
assertThatThrownBy(() -> underTest.upload(reportTempFolder.newFile()))
.isInstanceOf(MessageException.class)
MockWsResponse submitMockResponse = new MockWsResponse();
submitMockResponse.setContent(Ce.SubmitResponse.newBuilder().setTaskId("task-1234").build().toByteArray());
- when(wsClient.call(any(PostRequest.class))).thenReturn(submitMockResponse);
+ when(wsClient.call(any())).thenReturn(submitMockResponse);
underTest.start();
underTest.execute();
when(response.failIfNotSuccessful()).thenReturn(response);
when(response.contentStream()).thenReturn(in);
- when(wsClient.call(any(PostRequest.class))).thenReturn(response);
+ when(wsClient.call(any(WsRequest.class))).thenReturn(response);
underTest.upload(reportTempFolder.newFile());
- ArgumentCaptor<PostRequest> capture = ArgumentCaptor.forClass(PostRequest.class);
+ ArgumentCaptor<WsRequest> capture = ArgumentCaptor.forClass(WsRequest.class);
verify(wsClient).call(capture.capture());
WsRequest wsRequest = capture.getValue();
when(response.failIfNotSuccessful()).thenReturn(response);
when(response.contentStream()).thenReturn(in);
- when(wsClient.call(any(PostRequest.class))).thenReturn(response);
+ when(wsClient.call(any(WsRequest.class))).thenReturn(response);
underTest.upload(reportTempFolder.newFile());
- ArgumentCaptor<PostRequest> capture = ArgumentCaptor.forClass(PostRequest.class);
+ ArgumentCaptor<WsRequest> capture = ArgumentCaptor.forClass(WsRequest.class);
verify(wsClient).call(capture.capture());
WsRequest wsRequest = capture.getValue();
when(response.failIfNotSuccessful()).thenReturn(response);
when(response.contentStream()).thenReturn(in);
- when(wsClient.call(any(PostRequest.class))).thenReturn(response);
+ when(wsClient.call(any(WsRequest.class))).thenReturn(response);
underTest.upload(reportTempFolder.newFile());
- ArgumentCaptor<PostRequest> capture = ArgumentCaptor.forClass(PostRequest.class);
+ ArgumentCaptor<WsRequest> capture = ArgumentCaptor.forClass(WsRequest.class);
verify(wsClient).call(capture.capture());
WsRequest wsRequest = capture.getValue();
import org.sonar.scanner.WsTestUtil;
import org.sonar.scanner.bootstrap.DefaultScannerWsClient;
import org.sonarqube.ws.Batch.WsProjectResponse;
-import org.sonarqube.ws.client.GetRequest;
import org.sonarqube.ws.client.HttpException;
import static org.assertj.core.api.Assertions.assertThat;
@Test
public void continueOnHttp404Exception() {
- when(wsClient.call(any(GetRequest.class))).thenThrow(new HttpException("/batch/project.protobuf?key=foo%3F", HttpURLConnection.HTTP_NOT_FOUND, ""));
+ when(wsClient.call(any())).thenThrow(new HttpException("/batch/project.protobuf?key=foo%3F", HttpURLConnection.HTTP_NOT_FOUND, ""));
ProjectRepositories proj = loader.load(PROJECT_KEY, null);
assertThat(proj.exists()).isFalse();
}
@Test(expected = IllegalStateException.class)
public void failOnNonHttp404Exception() {
- when(wsClient.call(any(GetRequest.class))).thenThrow(IllegalStateException.class);
+ when(wsClient.call(any())).thenThrow(IllegalStateException.class);
ProjectRepositories proj = loader.load(PROJECT_KEY, null);
assertThat(proj.exists()).isFalse();
}
.writeTo(out);
out.close();
when(response.contentStream()).thenReturn(in);
- when(wsClient.call(any(GetRequest.class))).thenReturn(response);
+ when(wsClient.call(any())).thenReturn(response);
Map<String, String> result = underTest.loadGlobalSettings();
import java.util.Map;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
-import org.sonar.scanner.bootstrap.ScannerProperties;
import org.sonar.scanner.bootstrap.DefaultScannerWsClient;
+import org.sonar.scanner.bootstrap.ScannerProperties;
import org.sonarqube.ws.Settings;
import org.sonarqube.ws.client.GetRequest;
import org.sonarqube.ws.client.WsResponse;
.writeTo(out);
out.close();
when(response.contentStream()).thenReturn(in);
- when(wsClient.call(any(GetRequest.class))).thenReturn(response);
+ when(wsClient.call(any())).thenReturn(response);
when(properties.getProjectKey()).thenReturn("project_key");
Map<String, String> result = underTest.loadProjectSettings();