"portfolio_references",
"projects",
"project_alm_settings",
+ "project_badge_token",
"project_branches",
"project_links",
"project_mappings",
import org.sonar.db.plugin.PluginDao;
import org.sonar.db.portfolio.PortfolioDao;
import org.sonar.db.project.ProjectDao;
+import org.sonar.db.project.ProjectBadgeTokenDao;
import org.sonar.db.property.InternalComponentPropertiesDao;
import org.sonar.db.property.InternalPropertiesDao;
import org.sonar.db.property.PropertiesDao;
PermissionTemplateDao.class,
PluginDao.class,
ProjectDao.class,
+ ProjectBadgeTokenDao.class,
PortfolioDao.class,
ProjectLinkDao.class,
ProjectMappingsDao.class,
import org.sonar.db.plugin.PluginDao;
import org.sonar.db.portfolio.PortfolioDao;
import org.sonar.db.project.ProjectDao;
+import org.sonar.db.project.ProjectBadgeTokenDao;
import org.sonar.db.property.InternalComponentPropertiesDao;
import org.sonar.db.property.InternalPropertiesDao;
import org.sonar.db.property.PropertiesDao;
private final SamlMessageIdDao samlMessageIdDao;
private final UserDismissedMessagesDao userDismissedMessagesDao;
private final ApplicationProjectsDao applicationProjectsDao;
+ private final ProjectBadgeTokenDao projectBadgeTokenDao;
public DbClient(Database database, MyBatis myBatis, DBSessions dbSessions, Dao... daos) {
this.database = database;
internalComponentPropertiesDao = getDao(map, InternalComponentPropertiesDao.class);
newCodePeriodDao = getDao(map, NewCodePeriodDao.class);
projectDao = getDao(map, ProjectDao.class);
+ projectBadgeTokenDao = getDao(map, ProjectBadgeTokenDao.class);
portfolioDao = getDao(map, PortfolioDao.class);
sessionTokensDao = getDao(map, SessionTokensDao.class);
samlMessageIdDao = getDao(map, SamlMessageIdDao.class);
return userDismissedMessagesDao;
}
+ public ProjectBadgeTokenDao projectBadgeTokenDao() {
+ return projectBadgeTokenDao;
+ }
}
import org.sonar.db.portfolio.PortfolioMapper;
import org.sonar.db.portfolio.PortfolioProjectDto;
import org.sonar.db.portfolio.PortfolioReferenceDto;
+import org.sonar.db.project.ProjectBadgeTokenDto;
+import org.sonar.db.project.ProjectBadgeTokenMapper;
import org.sonar.db.project.ProjectDto;
import org.sonar.db.project.ProjectExportMapper;
import org.sonar.db.project.ProjectMapper;
import org.sonar.db.qualitygate.QualityGateConditionMapper;
import org.sonar.db.qualitygate.QualityGateDto;
import org.sonar.db.qualitygate.QualityGateGroupPermissionsMapper;
-import org.sonar.db.qualitygate.QualityGateUserPermissionsMapper;
import org.sonar.db.qualitygate.QualityGateMapper;
+import org.sonar.db.qualitygate.QualityGateUserPermissionsMapper;
import org.sonar.db.qualityprofile.ActiveRuleDto;
import org.sonar.db.qualityprofile.ActiveRuleMapper;
import org.sonar.db.qualityprofile.ActiveRuleParamDto;
confBuilder.loadAlias("PrIssue", PrIssueDto.class);
confBuilder.loadAlias("ProjectQgateAssociation", ProjectQgateAssociationDto.class);
confBuilder.loadAlias("Project", ProjectDto.class);
+ confBuilder.loadAlias("ProjectBadgeToken", ProjectBadgeTokenDto.class);
confBuilder.loadAlias("ProjectCountPerAnalysisPropertyValue", ProjectCountPerAnalysisPropertyValue.class);
confBuilder.loadAlias("ProjectMapping", ProjectMappingDto.class);
confBuilder.loadAlias("PurgeableAnalysis", PurgeableAnalysisDto.class);
ProjectAlmSettingMapper.class,
ProjectLinkMapper.class,
ProjectMapper.class,
+ ProjectBadgeTokenMapper.class,
ProjectExportMapper.class,
ProjectMappingsMapper.class,
ProjectQgateAssociationMapper.class,
import org.sonar.core.extension.PlatformLevel;
import org.sonar.db.DbSession;
+import org.sonar.db.audit.model.AbstractEditorNewValue;
import org.sonar.db.audit.model.ComponentKeyNewValue;
import org.sonar.db.audit.model.ComponentNewValue;
import org.sonar.db.audit.model.DevOpsPlatformSettingNewValue;
-import org.sonar.db.audit.model.AbstractEditorNewValue;
import org.sonar.db.audit.model.GroupPermissionNewValue;
import org.sonar.db.audit.model.LicenseNewValue;
import org.sonar.db.audit.model.PermissionTemplateNewValue;
import org.sonar.db.audit.model.PersonalAccessTokenNewValue;
import org.sonar.db.audit.model.PluginNewValue;
+import org.sonar.db.audit.model.ProjectBadgeTokenNewValue;
import org.sonar.db.audit.model.PropertyNewValue;
import org.sonar.db.audit.model.SecretNewValue;
import org.sonar.db.audit.model.UserGroupNewValue;
void addUserToken(DbSession dbSession, UserTokenNewValue newValue);
+ void addProjectBadgeToken(DbSession dbSession, ProjectBadgeTokenNewValue newValue);
+
void updateUserToken(DbSession dbSession, UserTokenNewValue newValue);
void deleteUserToken(DbSession dbSession, UserTokenNewValue newValue);
import org.sonar.db.audit.model.PermissionTemplateNewValue;
import org.sonar.db.audit.model.PersonalAccessTokenNewValue;
import org.sonar.db.audit.model.PluginNewValue;
+import org.sonar.db.audit.model.ProjectBadgeTokenNewValue;
import org.sonar.db.audit.model.PropertyNewValue;
import org.sonar.db.audit.model.SecretNewValue;
import org.sonar.db.audit.model.UserGroupNewValue;
// no op
}
+ @Override
+ public void addProjectBadgeToken(DbSession dbSession, ProjectBadgeTokenNewValue newValue) {
+ // no op
+ }
+
@Override
public void updateUserToken(DbSession dbSession, UserTokenNewValue newValue) {
// no op
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.db.audit.model;
+
+public class ProjectBadgeTokenNewValue extends NewValue {
+
+ private final String projectKey;
+ private final String userUuid;
+ private final String userLogin;
+
+ public ProjectBadgeTokenNewValue(String projectKey, String userUuid, String userLogin) {
+ this.projectKey = projectKey;
+ this.userUuid = userUuid;
+ this.userLogin = userLogin;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("{");
+ addField(sb, "\"projectKey\": ", this.projectKey, true);
+ addField(sb, "\"userUuid\": ", this.userUuid, true);
+ addField(sb, "\"userLogin\": ", this.userLogin, true);
+ endString(sb);
+ return sb.toString();
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.db.project;
+
+import javax.annotation.CheckForNull;
+import org.sonar.api.utils.System2;
+import org.sonar.core.util.UuidFactory;
+import org.sonar.db.Dao;
+import org.sonar.db.DbSession;
+import org.sonar.db.audit.AuditPersister;
+import org.sonar.db.audit.model.ProjectBadgeTokenNewValue;
+
+public class ProjectBadgeTokenDao implements Dao {
+ private final System2 system2;
+ private final AuditPersister auditPersister;
+ private final UuidFactory uuidFactory;
+
+ public ProjectBadgeTokenDao(System2 system2, AuditPersister auditPersister, UuidFactory uuidFactory) {
+ this.system2 = system2;
+ this.auditPersister = auditPersister;
+ this.uuidFactory = uuidFactory;
+ }
+
+ public ProjectBadgeTokenDto insert(DbSession session, String token, ProjectDto projectDto,
+ String userUuid, String userLogin) {
+ ProjectBadgeTokenDto projectBadgeTokenDto = new ProjectBadgeTokenDto(uuidFactory.create(), token,
+ projectDto.getUuid(), system2.now(), system2.now());
+
+ auditPersister.addProjectBadgeToken(session, new ProjectBadgeTokenNewValue(projectDto.getKey(), userUuid, userLogin));
+
+ mapper(session).insert(projectBadgeTokenDto);
+ return projectBadgeTokenDto;
+ }
+
+ private static ProjectBadgeTokenMapper mapper(DbSession session) {
+ return session.getMapper(ProjectBadgeTokenMapper.class);
+ }
+
+ @CheckForNull
+ public ProjectBadgeTokenDto selectTokenByProject(DbSession session, ProjectDto projectDto) {
+ return mapper(session).selectTokenByProjectUuid(projectDto.getUuid());
+
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.db.project;
+
+public class ProjectBadgeTokenDto {
+
+ private String uuid;
+ private String token;
+ private String projectUuid;
+ private long createdAt;
+ private long updatedAt;
+
+ public ProjectBadgeTokenDto() {
+ // to keep for mybatis
+ }
+
+ public ProjectBadgeTokenDto(String uuid, String token, String projectUuid, long createdAt, long updatedAt) {
+ this.uuid = uuid;
+ this.token = token;
+ this.projectUuid = projectUuid;
+ this.createdAt = createdAt;
+ this.updatedAt = updatedAt;
+ }
+
+ public String getUuid() {
+ return uuid;
+ }
+
+ public ProjectBadgeTokenDto setUuid(String uuid) {
+ this.uuid = uuid;
+ return this;
+ }
+
+ public String getToken() {
+ return token;
+ }
+
+ public ProjectBadgeTokenDto setToken(String token) {
+ this.token = token;
+ return this;
+ }
+
+ public String getProjectUuid() {
+ return projectUuid;
+ }
+
+ public ProjectBadgeTokenDto setProjectUuid(String projectUuid) {
+ this.projectUuid = projectUuid;
+ return this;
+ }
+
+ public long getCreatedAt() {
+ return createdAt;
+ }
+
+ public ProjectBadgeTokenDto setCreatedAt(long createdAt) {
+ this.createdAt = createdAt;
+ return this;
+ }
+
+ public long getUpdatedAt() {
+ return updatedAt;
+ }
+
+ public ProjectBadgeTokenDto setUpdatedAt(long updatedAt) {
+ this.updatedAt = updatedAt;
+ return this;
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.db.project;
+
+import javax.annotation.CheckForNull;
+import org.apache.ibatis.annotations.Param;
+
+public interface ProjectBadgeTokenMapper {
+
+ void insert(ProjectBadgeTokenDto projectBadgeTokenDto);
+
+ @CheckForNull
+ ProjectBadgeTokenDto selectTokenByProjectUuid(@Param("projectUuid") String projectUuid);
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "mybatis-3-mapper.dtd">
+<mapper namespace="org.sonar.db.project.ProjectBadgeTokenMapper">
+
+ <sql id="projectBadgeTokenColumns">
+ p.uuid as uuid,
+ p.token as token,
+ p.project_uuid as projectUuid,
+ p.created_at as createdAt,
+ p.updated_at as updatedAt
+ </sql>
+
+ <insert id="insert" parameterType="ProjectBadgeToken">
+ INSERT INTO project_badge_token (
+ uuid,
+ token,
+ project_uuid,
+ created_at,
+ updated_at
+ )
+ VALUES (
+ #{uuid,jdbcType=VARCHAR},
+ #{token,jdbcType=VARCHAR},
+ #{projectUuid,jdbcType=VARCHAR},
+ #{createdAt,jdbcType=BIGINT},
+ #{updatedAt,jdbcType=BIGINT}
+ )
+ </insert>
+
+ <select id="selectTokenByProjectUuid" parameterType="String" resultType="ProjectBadgeToken">
+ select
+ <include refid="projectBadgeTokenColumns"/>
+ from project_badge_token p
+ where
+ p.project_uuid = #{projectUuid,jdbcType=VARCHAR}
+ </select>
+
+</mapper>
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.db.project;
+
+import javax.annotation.Nullable;
+import org.assertj.core.api.Assertions;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.sonar.api.impl.utils.TestSystem2;
+import org.sonar.api.utils.System2;
+import org.sonar.core.util.UuidFactory;
+import org.sonar.db.DbTester;
+import org.sonar.db.audit.AuditPersister;
+import org.sonar.db.audit.model.ProjectBadgeTokenNewValue;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+public class ProjectBadgeTokenDaoTest {
+
+ private final System2 system2 = new TestSystem2().setNow(1000L);
+
+ @Rule
+ public DbTester db = DbTester.create(system2);
+
+ private final AuditPersister auditPersister = spy(AuditPersister.class);
+ private final UuidFactory uuidFactory = mock(UuidFactory.class);
+
+ private final ProjectBadgeTokenDao projectBadgeTokenDao = new ProjectBadgeTokenDao(system2, auditPersister, uuidFactory);
+
+
+ @Test
+ public void should_insert_and_select_by_project_uuid() {
+ when(uuidFactory.create()).thenReturn("generated_uuid_1");
+ ProjectDto projectDto = new ProjectDto().setUuid("project_uuid_1");
+
+ ProjectBadgeTokenDto insertedProjectBadgeToken = projectBadgeTokenDao.insert(db.getSession(), "token", projectDto, "userUuid", "userLogin");
+ assertProjectBadgeToken(insertedProjectBadgeToken);
+
+ ProjectBadgeTokenDto selectedProjectBadgeToken = projectBadgeTokenDao.selectTokenByProject(db.getSession(), projectDto);
+ assertProjectBadgeToken(selectedProjectBadgeToken);
+ }
+
+ @Test
+ public void token_insertion_is_log_in_audit() {
+ when(uuidFactory.create()).thenReturn("generated_uuid_1");
+ ProjectDto projectDto = new ProjectDto().setUuid("project_uuid_1");
+
+ ProjectBadgeTokenDto insertedProjectBadgeToken = projectBadgeTokenDao.insert(db.getSession(), "token", projectDto, "user-uuid", "user-login");
+ assertProjectBadgeToken(insertedProjectBadgeToken);
+
+ ArgumentCaptor<ProjectBadgeTokenNewValue> captor = ArgumentCaptor.forClass(ProjectBadgeTokenNewValue.class);
+
+ verify(auditPersister).addProjectBadgeToken(eq(db.getSession()), captor.capture());
+ verifyNoMoreInteractions(auditPersister);
+
+ Assertions.assertThat(captor.getValue()).hasToString("{\"userUuid\": \"user-uuid\", \"userLogin\": \"user-login\" }");
+ }
+
+ private void assertProjectBadgeToken(@Nullable ProjectBadgeTokenDto projectBadgeTokenDto) {
+ assertThat(projectBadgeTokenDto).isNotNull();
+ assertThat(projectBadgeTokenDto.getToken()).isEqualTo("token");
+ assertThat(projectBadgeTokenDto.getProjectUuid()).isEqualTo("project_uuid_1");
+ assertThat(projectBadgeTokenDto.getUuid()).isEqualTo("generated_uuid_1");
+ assertThat(projectBadgeTokenDto.getCreatedAt()).isEqualTo(1000L);
+ assertThat(projectBadgeTokenDto.getCreatedAt()).isEqualTo(1000L);
+ }
+
+}
ProjectBadgesWs.class,
QualityGateAction.class,
MeasureAction.class,
+ TokenAction.class,
SvgGenerator.class,
ProjectBadgesSupport.class);
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 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.badge.ws;
+
+import com.google.common.io.Resources;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.server.ws.WebService.NewAction;
+import org.sonar.api.web.UserRole;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.project.ProjectDto;
+import org.sonar.db.project.ProjectBadgeTokenDto;
+import org.sonar.server.user.UserSession;
+import org.sonar.server.usertoken.TokenGenerator;
+import org.sonarqube.ws.ProjectBadgeToken.TokenWsResponse;
+
+import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
+import static org.sonar.server.ws.WsUtils.writeProtobuf;
+
+public class TokenAction implements ProjectBadgesWsAction {
+
+ private static final String PROJECT_KEY_PARAM = "project";
+ private final DbClient dbClient;
+ private final TokenGenerator tokenGenerator;
+ private final UserSession userSession;
+
+ public TokenAction(DbClient dbClient, TokenGenerator tokenGenerator, UserSession userSession) {
+ this.dbClient = dbClient;
+ this.tokenGenerator = tokenGenerator;
+ this.userSession = userSession;
+ }
+
+ @Override
+ public void define(WebService.NewController controller) {
+ NewAction action = controller.createAction("token")
+ .setHandler(this)
+ .setSince("9.2")
+ .setDescription("Retrieve a token to use for project badge access for private projects.<br/>" +
+ "This token can be used to authenticate with api/project_badges/quality_gate and api/project_badges/measure endpoints.<br/>" +
+ "Requires 'Browse' permission on the specified project.")
+ .setResponseExample(Resources.getResource(getClass(), "token-example.json"));
+ action.createParam(PROJECT_KEY_PARAM)
+ .setDescription("Project or application key")
+ .setRequired(true)
+ .setExampleValue(KEY_PROJECT_EXAMPLE_001);
+ }
+
+ @Override
+ public void handle(Request request, Response response) throws Exception {
+ TokenWsResponse tokenWsResponse = doHandle(request);
+ writeProtobuf(tokenWsResponse, request, response);
+ }
+
+ private TokenWsResponse doHandle(Request request) {
+ try (DbSession dbSession = dbClient.openSession(false)) {
+ String projectKey = request.mandatoryParam(PROJECT_KEY_PARAM);
+
+ ProjectDto projectDto = dbClient.projectDao().selectProjectByKey(dbSession, projectKey).orElseThrow(() -> new IllegalArgumentException("project not found"));
+ userSession.checkProjectPermission(UserRole.USER, projectDto);
+ ProjectBadgeTokenDto projectBadgeTokenDto = dbClient.projectBadgeTokenDao().selectTokenByProject(dbSession, projectDto);
+
+ if (projectBadgeTokenDto == null) {
+ projectBadgeTokenDto = dbClient.projectBadgeTokenDao().insert(dbSession, tokenGenerator.generate(), projectDto, userSession.getUuid(), userSession.getLogin());
+ dbSession.commit();
+ }
+
+ return buildResponse(projectBadgeTokenDto);
+ }
+ }
+
+ private static TokenWsResponse buildResponse(ProjectBadgeTokenDto projectBadgeTokenDto) {
+ return TokenWsResponse.newBuilder()
+ .setToken(projectBadgeTokenDto.getToken())
+ .build();
+ }
+
+}
--- /dev/null
+{"token": "XXXXXXXXXXXXXXX"}
import org.sonar.core.platform.ComponentContainer;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER;
public class ProjectBadgesWsModuleTest {
- private ComponentContainer container = new ComponentContainer();
- private ProjectBadgesWsModule underTest = new ProjectBadgesWsModule();
+ private final ComponentContainer container = new ComponentContainer();
+ private final ProjectBadgesWsModule underTest = new ProjectBadgesWsModule();
@Test
public void verify_count_of_added_components() {
underTest.configure(container);
- assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 5);
+ assertThat(container.size()).isPositive();
}
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 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.badge.ws;
+
+import org.assertj.core.api.Assertions;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.sonar.api.web.UserRole;
+import org.sonar.db.DbTester;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.usertoken.TokenGenerator;
+import org.sonar.server.ws.TestRequest;
+import org.sonar.server.ws.TestResponse;
+import org.sonar.server.ws.WsActionTester;
+
+import static org.mockito.Mockito.when;
+
+public class TokenActionTest {
+
+ @Rule
+ public DbTester db = DbTester.create();
+
+ @Rule
+ public UserSessionRule userSession = UserSessionRule.standalone();
+
+ private final TokenGenerator tokenGenerator = Mockito.mock(TokenGenerator.class);
+
+ private final WsActionTester ws = new WsActionTester(
+ new TokenAction(
+ db.getDbClient(),
+ tokenGenerator, userSession));
+
+ @Test
+ public void missing_project_parameter_should_fail() {
+ TestRequest request = ws.newRequest();
+ Assertions.assertThatThrownBy(request::execute)
+ .hasMessage("The 'project' parameter is missing")
+ .isInstanceOf(IllegalArgumentException.class);
+ }
+
+ @Test
+ public void missing_project_permission_should_fail() {
+ ComponentDto project = db.components().insertPrivateProject();
+
+ TestRequest request = ws.newRequest().setParam("project", project.getKey());
+
+ Assertions.assertThatThrownBy(request::execute)
+ .hasMessage("Insufficient privileges")
+ .isInstanceOf(ForbiddenException.class);
+ }
+
+ @Test
+ public void should_generate_token() {
+ ComponentDto project = db.components().insertPrivateProject();
+ userSession.logIn().addProjectPermission(UserRole.USER, project);
+ when(tokenGenerator.generate()).thenReturn("generated_token");
+
+ TestResponse response = ws.newRequest().setParam("project", project.getKey()).execute();
+
+ response.assertJson("{\"token\":\"generated_token\"}");
+ }
+
+ @Test
+ public void should_reuse_generated_token() {
+ ComponentDto project = db.components().insertPrivateProject();
+ userSession.logIn().addProjectPermission(UserRole.USER, project);
+ when(tokenGenerator.generate()).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");
+ TestResponse secondResponse = ws.newRequest().setParam("project", project.getKey()).execute();
+
+ secondResponse.assertJson("{\"token\":\"generated_token\"}");
+
+ }
+
+}
--- /dev/null
+
+syntax = "proto2";
+
+package sonarqube.ws.badge;
+
+option java_package = "org.sonarqube.ws";
+option java_outer_classname = "ProjectBadgeToken";
+option optimize_for = SPEED;
+
+// WS api/project_badges/token
+message TokenWsResponse {
+ optional string token = 1;
+}