* must not contain colon character ":".
*
*/
- String generate();
+ String generate(TokenType tokenType);
/**
* Hash a token.<br/>
import org.apache.commons.codec.digest.DigestUtils;
public class TokenGeneratorImpl implements TokenGenerator {
+
+ private static final String SONARQUBE_TOKEN_PREFIX = "sq";
+
@Override
- public String generate() {
+ public String generate(TokenType tokenType) {
SecureRandom random = new SecureRandom();
- byte[] bytes = new byte[20];
- random.nextBytes(bytes);
- return Hex.encodeHexString(bytes);
+ byte[] randomBytes = new byte[20];
+ random.nextBytes(randomBytes);
+ return buildIdentifiablePartOfToken(tokenType) + Hex.encodeHexString(randomBytes);
+ }
+
+ private static String buildIdentifiablePartOfToken(TokenType tokenType) {
+ return SONARQUBE_TOKEN_PREFIX + tokenType.getIdentifier() + "_";
}
@Override
--- /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.usertoken;
+
+public enum TokenType {
+ USER_TOKEN("u");
+
+ private final String identifier;
+
+ TokenType(String identifier) {
+ this.identifier = identifier;
+ }
+
+ public String getIdentifier() {
+ return identifier;
+ }
+}
import static org.assertj.core.api.Assertions.assertThat;
public class TokenGeneratorImplTest {
- TokenGeneratorImpl underTest = new TokenGeneratorImpl();
+ private TokenGeneratorImpl underTest = new TokenGeneratorImpl();
@Test
public void generate_different_tokens() {
// this test is not enough to ensure that generated strings are unique,
// but it still does a simple and stupid verification
- String firstToken = underTest.generate();
- String secondToken = underTest.generate();
+ String firstToken = underTest.generate(TokenType.USER_TOKEN);
+ String secondToken = underTest.generate(TokenType.USER_TOKEN);
assertThat(firstToken)
.isNotEqualTo(secondToken)
- .hasSize(40);
+ .hasSize(44);
+ }
+
+ @Test
+ public void generate_tokenShouldHaveSonarQubePrefix() {
+ String token = underTest.generate(TokenType.USER_TOKEN);
+
+ assertThat(token).matches("squ_.*");
}
@Test
public void token_does_not_contain_colon() {
- assertThat(underTest.generate()).doesNotContain(":");
+ assertThat(underTest.generate(TokenType.USER_TOKEN)).doesNotContain(":");
}
@Test
import org.sonar.db.project.ProjectBadgeTokenDto;
import org.sonar.server.user.UserSession;
import org.sonar.server.usertoken.TokenGenerator;
+import org.sonar.server.usertoken.TokenType;
import org.sonarqube.ws.ProjectBadgeToken.TokenWsResponse;
import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
ProjectBadgeTokenDto projectBadgeTokenDto = dbClient.projectBadgeTokenDao().selectTokenByProject(dbSession, projectDto);
if (projectBadgeTokenDto == null) {
- projectBadgeTokenDto = dbClient.projectBadgeTokenDao().insert(dbSession, tokenGenerator.generate(), projectDto, userSession.getUuid(), userSession.getLogin());
+ projectBadgeTokenDto = dbClient.projectBadgeTokenDao().insert(dbSession, tokenGenerator.generate(TokenType.USER_TOKEN),
+ projectDto, userSession.getUuid(), userSession.getLogin());
dbSession.commit();
}
import org.sonar.db.project.ProjectDto;
import org.sonar.server.user.UserSession;
import org.sonar.server.usertoken.TokenGenerator;
+import org.sonar.server.usertoken.TokenType;
import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
ProjectDto projectDto = dbClient.projectDao().selectProjectByKey(dbSession, projectKey).orElseThrow(() -> new IllegalArgumentException("project not found"));
userSession.checkProjectPermission(UserRole.ADMIN, projectDto);
- String newGeneratedToken = tokenGenerator.generate();
+ String newGeneratedToken = tokenGenerator.generate(TokenType.USER_TOKEN);
dbClient.projectBadgeTokenDao().upsert(dbSession, newGeneratedToken, projectDto, userSession.getUuid(), userSession.getLogin());
dbSession.commit();
}
import org.sonar.db.user.UserTokenDto;
import org.sonar.server.exceptions.ServerException;
import org.sonar.server.usertoken.TokenGenerator;
+import org.sonar.server.usertoken.TokenType;
import org.sonarqube.ws.UserTokens;
import org.sonarqube.ws.UserTokens.GenerateWsResponse;
UserDto user = userTokenSupport.getUser(dbSession, request);
checkTokenDoesNotAlreadyExists(dbSession, user, name);
- String token = tokenGenerator.generate();
+ String token = tokenGenerator.generate(TokenType.USER_TOKEN);
String tokenHash = hashToken(dbSession, token);
UserTokenDto userTokenDto = insertTokenInDb(dbSession, user, name, tokenHash);
return buildResponse(userTokenDto, token, user);
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.usertoken.TokenGenerator;
+import org.sonar.server.usertoken.TokenType;
import org.sonar.server.ws.TestRequest;
import org.sonar.server.ws.TestResponse;
import org.sonar.server.ws.WsActionTester;
public void should_generate_token() {
ComponentDto project = db.components().insertPrivateProject();
userSession.logIn().addProjectPermission(UserRole.USER, project);
- when(tokenGenerator.generate()).thenReturn("generated_token");
+ when(tokenGenerator.generate(TokenType.USER_TOKEN)).thenReturn("generated_token");
TestResponse response = ws.newRequest().setParam("project", project.getKey()).execute();
public void should_reuse_generated_token() {
ComponentDto project = db.components().insertPrivateProject();
userSession.logIn().addProjectPermission(UserRole.USER, project);
- when(tokenGenerator.generate()).thenReturn("generated_token");
+ when(tokenGenerator.generate(TokenType.USER_TOKEN)).thenReturn("generated_token");
// first call, generating the token
TestResponse firstResponse = ws.newRequest().setParam("project", project.getKey()).execute();
firstResponse.assertJson("{\"token\":\"generated_token\"}");
// 2nd call, reusing the existing token
- when(tokenGenerator.generate()).thenReturn("never_generated_token");
+ when(tokenGenerator.generate(TokenType.USER_TOKEN)).thenReturn("never_generated_token");
TestResponse secondResponse = ws.newRequest().setParam("project", project.getKey()).execute();
secondResponse.assertJson("{\"token\":\"generated_token\"}");
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.usertoken.TokenGenerator;
+import org.sonar.server.usertoken.TokenType;
import org.sonar.server.ws.TestRequest;
import org.sonar.server.ws.TestResponse;
import org.sonar.server.ws.WsActionTester;
public void should_add_token_when_no_token_yet_and_return_204() {
ProjectDto project = db.components().insertPrivateProjectDto();
userSession.logIn().addProjectPermission(UserRole.ADMIN, project);
- when(tokenGenerator.generate()).thenReturn("generated_token");
+ when(tokenGenerator.generate(TokenType.USER_TOKEN)).thenReturn("generated_token");
TestResponse response = ws.newRequest().setParam("project", project.getKey()).execute();
public void should_replace_existing_token_when__token_already_present_and_update_update_at() {
ProjectDto project = db.components().insertPrivateProjectDto();
userSession.logIn().addProjectPermission(UserRole.ADMIN, project);
- when(tokenGenerator.generate()).thenReturn("generated_token");
+ when(tokenGenerator.generate(TokenType.USER_TOKEN)).thenReturn("generated_token");
ws.newRequest().setParam("project", project.getKey()).execute(); //inserting first token with updated at 1000
import org.sonar.server.exceptions.UnauthorizedException;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.usertoken.TokenGenerator;
+import org.sonar.server.usertoken.TokenType;
import org.sonar.server.ws.TestRequest;
import org.sonar.server.ws.WsActionTester;
import org.sonarqube.ws.MediaTypes;
@Before
public void setUp() {
- when(tokenGenerator.generate()).thenReturn("123456789");
+ when(tokenGenerator.generate(TokenType.USER_TOKEN)).thenReturn("123456789");
when(tokenGenerator.hash(anyString())).thenReturn("987654321");
}