assertThat(picoContainer.getParent().getParent().getParent().getComponentAdapters()).hasSize(
COMPONENTS_IN_LEVEL_1_AT_CONSTRUCTION
+ 24 // level 1
- + 52 // content of DaoModule
+ + 53 // content of DaoModule
+ 2 // content of EsSearchModule
+ 62 // content of CorePropertyDefinitions
+ 1 // content of CePropertyDefinitions
import org.sonar.db.metric.MetricDao;
import org.sonar.db.notification.NotificationQueueDao;
import org.sonar.db.organization.OrganizationDao;
+import org.sonar.db.permission.AuthorizationDao;
import org.sonar.db.permission.GroupPermissionDao;
import org.sonar.db.permission.UserPermissionDao;
import org.sonar.db.permission.template.PermissionTemplateCharacteristicDao;
private static final List<Class<? extends Dao>> classes = ImmutableList.<Class<? extends Dao>>builder().add(
ActiveDashboardDao.class,
AuthorDao.class,
+ AuthorizationDao.class,
PermissionDao.class,
CeActivityDao.class,
CeQueueDao.class,
import org.sonar.db.metric.MetricDao;
import org.sonar.db.notification.NotificationQueueDao;
import org.sonar.db.organization.OrganizationDao;
+import org.sonar.db.permission.AuthorizationDao;
import org.sonar.db.permission.GroupPermissionDao;
import org.sonar.db.permission.PermissionDao;
import org.sonar.db.permission.UserPermissionDao;
private final Database database;
private final MyBatis myBatis;
+ private final AuthorizationDao authorizationDao;
private final OrganizationDao organizationDao;
private final QualityProfileDao qualityProfileDao;
private final LoadedTemplateDao loadedTemplateDao;
for (Dao dao : daos) {
map.put(dao.getClass(), dao);
}
+ authorizationDao = getDao(map, AuthorizationDao.class);
organizationDao = getDao(map, OrganizationDao.class);
qualityProfileDao = getDao(map, QualityProfileDao.class);
loadedTemplateDao = getDao(map, LoadedTemplateDao.class);
return database;
}
+ public AuthorizationDao authorizationDao() {
+ return authorizationDao;
+ }
+
public OrganizationDao organizationDao() {
return organizationDao;
}
import org.sonar.db.notification.NotificationQueueMapper;
import org.sonar.db.organization.OrganizationDto;
import org.sonar.db.organization.OrganizationMapper;
+import org.sonar.db.permission.AuthorizationMapper;
import org.sonar.db.permission.GroupPermissionDto;
import org.sonar.db.permission.GroupPermissionMapper;
import org.sonar.db.permission.PermissionMapper;
ActiveDashboardMapper.class,
ActiveRuleMapper.class,
AuthorMapper.class,
+ AuthorizationMapper.class,
CeActivityMapper.class,
CeQueueMapper.class,
CeScannerContextMapper.class,
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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.permission;
+
+import java.util.Set;
+import org.sonar.db.Dao;
+import org.sonar.db.DbSession;
+
+/**
+ * The SQL requests used to verify authorization (the permissions
+ * granted to users)
+ *
+ * @see GroupPermissionDao for CRUD of table group_roles
+ * @see UserPermissionDao for CRUD of table user_roles
+ */
+public class AuthorizationDao implements Dao {
+
+ /**
+ * Loads all the permissions granted to logged-in user for the specified organization
+ */
+ public Set<String> selectOrganizationPermissions(DbSession dbSession, String organizationUuid, long userId) {
+ return mapper(dbSession).selectOrganizationPermissions(organizationUuid, userId);
+ }
+
+ /**
+ * Loads all the permissions granted to anonymous user for the specified organization
+ */
+ public Set<String> selectOrganizationPermissionsOfAnonymous(DbSession dbSession, String organizationUuid) {
+ return mapper(dbSession).selectOrganizationPermissionsOfAnonymous(organizationUuid);
+ }
+
+ /**
+ * Loads all the permissions granted to logged-in user for the specified root component (project)
+ */
+ public Set<String> selectRootComponentPermissions(DbSession dbSession, long rootComponentId, long userId) {
+ return mapper(dbSession).selectRootComponentPermissions(rootComponentId, userId);
+ }
+
+ /**
+ * Loads all the permissions granted to anonymous user for the specified root component (project)
+ */
+ public Set<String> selectRootComponentPermissionsOfAnonymous(DbSession dbSession, long rootComponentId) {
+ return mapper(dbSession).selectRootComponentPermissionsOfAnonymous(rootComponentId);
+ }
+
+ private static AuthorizationMapper mapper(DbSession dbSession) {
+ return dbSession.getMapper(AuthorizationMapper.class);
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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.permission;
+
+import java.util.Set;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * @see AuthorizationDao
+ */
+public interface AuthorizationMapper {
+
+ Set<String> selectOrganizationPermissions(@Param("organizationUuid") String organizationUuid,
+ @Param("userId") long userId);
+
+ Set<String> selectOrganizationPermissionsOfAnonymous(@Param("organizationUuid") String organizationUuid);
+
+ Set<String> selectRootComponentPermissions(@Param("rootComponentId") long rootComponentId, @Param("userId") long userId);
+
+ Set<String> selectRootComponentPermissionsOfAnonymous(@Param("rootComponentId") long rootComponentId);
+
+}
/**
* Only the requests involving both user and group permissions.
*
- * @see GroupPermissionMapper
- * @see UserPermissionMapper
+ * @see GroupPermissionMapper for CRUD of table group_roles
+ * @see UserPermissionMapper for CRUD of table user_roles
*/
public interface PermissionMapper {
this.settings = settings;
}
- /**
- * For each modification of permission on a project, update the authorization_updated_at to help ES reindex only relevant changes
- */
- private void updateProjectAuthorizationDate(DbSession session, @Nullable Long projectId) {
- if (projectId != null) {
- dbClient.resourceDao().updateAuthorizationDate(projectId, session);
- }
- }
-
public void applyPermissionTemplate(DbSession session, String templateUuid, ComponentDto project) {
applyPermissionTemplate(session, templateUuid, project, null);
}
}
}
+ /**
+ * For each modification of permission on a project, update the authorization_updated_at to help ES reindex only relevant changes
+ */
+ private void updateProjectAuthorizationDate(DbSession dbSession, long projectId) {
+ dbClient.resourceDao().updateAuthorizationDate(projectId, dbSession);
+ }
+
/**
* Warning, this method is also used by the Developer Cockpit plugin
*/
* permission template for the resource qualifier.
*/
private String getApplicablePermissionTemplateKey(DbSession session, final String componentKey, String qualifier) {
+ // FIXME performance issue here, we should not load all templates
List<PermissionTemplateDto> allPermissionTemplates = dbClient.permissionTemplateDao().selectAll(session);
List<PermissionTemplateDto> matchingTemplates = new ArrayList<>();
for (PermissionTemplateDto permissionTemplateDto : allPermissionTemplates) {
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+
+<mapper namespace="org.sonar.db.permission.AuthorizationMapper">
+
+ <select id="selectOrganizationPermissions" parameterType="map" resultType="string">
+ select gr.role
+ from group_roles gr
+ where
+ gr.organization_uuid=#{organizationUuid,jdbcType=VARCHAR} and
+ gr.resource_id is null and
+ (gr.group_id is null or gr.group_id in (select gu.group_id from groups_users gu where gu.user_id=#{userId,jdbcType=BIGINT}))
+ union
+ select ur.role
+ from user_roles ur
+ where
+ ur.organization_uuid=#{organizationUuid,jdbcType=VARCHAR} and
+ ur.user_id=#{userId,jdbcType=BIGINT}
+ </select>
+
+ <select id="selectOrganizationPermissionsOfAnonymous" parameterType="map" resultType="string">
+ select gr.role
+ from group_roles gr
+ where
+ gr.organization_uuid=#{organizationUuid,jdbcType=VARCHAR} and
+ gr.resource_id is null and
+ gr.group_id is null
+ </select>
+
+ <select id="selectRootComponentPermissions" parameterType="map" resultType="string">
+ select gr.role
+ from group_roles gr
+ where
+ gr.resource_id=#{rootComponentId,jdbcType=BIGINT} and
+ (gr.group_id is null or gr.group_id in (select gu.group_id from groups_users gu where gu.user_id=#{userId,jdbcType=BIGINT}))
+ union
+ select ur.role
+ from user_roles ur
+ where
+ ur.resource_id=#{rootComponentId,jdbcType=BIGINT} and
+ ur.user_id=#{userId,jdbcType=BIGINT}
+ </select>
+
+ <select id="selectRootComponentPermissionsOfAnonymous" parameterType="map" resultType="string">
+ select gr.role
+ from group_roles gr
+ where
+ gr.resource_id=#{rootComponentId,jdbcType=BIGINT} and
+ gr.group_id is null
+ </select>
+
+</mapper>
public void verify_count_of_added_components() {
ComponentContainer container = new ComponentContainer();
new DaoModule().configure(container);
- assertThat(container.size()).isEqualTo(2 + 52);
+ assertThat(container.size()).isEqualTo(2 + 53);
}
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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.permission;
+
+import java.util.Set;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.db.organization.OrganizationDto;
+import org.sonar.db.organization.OrganizationTesting;
+import org.sonar.db.user.GroupDto;
+import org.sonar.db.user.UserDto;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.db.organization.OrganizationTesting.newOrganizationDto;
+
+public class AuthorizationDaoTest {
+
+ @Rule
+ public DbTester db = DbTester.create(System2.INSTANCE);
+ private DbSession dbSession = db.getSession();
+ private AuthorizationDao underTest = new AuthorizationDao();
+ private OrganizationDto org;
+ private UserDto user;
+ private GroupDto group1;
+ private GroupDto group2;
+
+ @Before
+ public void setUp() throws Exception {
+ org = OrganizationTesting.insert(db, newOrganizationDto());
+ user = db.users().insertUser();
+ group1 = db.users().insertGroup(org, "group1");
+ group2 = db.users().insertGroup(org, "group2");
+ }
+
+ /**
+ * Union of the permissions granted to:
+ * - the user
+ * - the groups which user is member
+ * - anyone
+ */
+ @Test
+ public void selectOrganizationPermissions_for_logged_in_user() {
+ db.users().insertMember(group1, user);
+ db.users().insertPermissionOnUser(org, user, "perm1");
+ db.users().insertPermissionOnGroup(group1, "perm2");
+ db.users().insertPermissionOnAnyone(org, "perm3");
+
+ // ignored permissions, user is not member of this group
+ db.users().insertPermissionOnGroup(group2, "ignored");
+
+ Set<String> permissions = underTest.selectOrganizationPermissions(dbSession, org.getUuid(), user.getId());
+
+ assertThat(permissions).containsOnly("perm1", "perm2", "perm3");
+ }
+
+ /**
+ * Anonymous user only benefits from the permissions granted to
+ * "Anyone"
+ */
+ @Test
+ public void selectOrganizationPermissions_for_anonymous_user() {
+ db.users().insertPermissionOnAnyone(org, "perm1");
+
+ // ignored permissions
+ db.users().insertPermissionOnUser(org, user, "ignored");
+ db.users().insertPermissionOnGroup(group1, "ignored");
+
+ Set<String> permissions = underTest.selectOrganizationPermissionsOfAnonymous(dbSession, org.getUuid());
+
+ assertThat(permissions).containsOnly("perm1");
+ }
+
+ /**
+ * Union of the permissions granted to:
+ * - the user
+ * - the groups which user is member
+ * - anyone
+ */
+ @Test
+ public void selectRootComponentPermissions_for_logged_in_user() {
+ db.users().insertMember(group1, user);
+ ComponentDto project1 = db.components().insertProject();
+ db.users().insertProjectPermissionOnAnyone("perm1", project1);
+ db.users().insertProjectPermissionOnGroup(group1, "perm2", project1);
+ db.users().insertProjectPermissionOnUser(user, "perm3", project1);
+
+ // ignored permissions
+ db.users().insertPermissionOnAnyone(org, "ignored");
+ db.users().insertPermissionOnGroup(group2, "ignored");
+ ComponentDto project2 = db.components().insertProject();
+
+ Set<String> permissions = underTest.selectRootComponentPermissions(dbSession, project1.getId(), user.getId());
+ assertThat(permissions).containsOnly("perm1", "perm2", "perm3");
+
+ // non granted project
+ permissions = underTest.selectRootComponentPermissions(dbSession, project2.getId(), user.getId());
+ assertThat(permissions).isEmpty();
+ }
+
+ /**
+ * Anonymous user only benefits from the permissions granted to
+ * "Anyone"
+ */
+ @Test
+ public void selectRootComponentPermissions_for_anonymous_user() {
+ ComponentDto project1 = db.components().insertProject();
+ db.users().insertProjectPermissionOnAnyone("perm1", project1);
+
+ // ignored permissions
+ db.users().insertPermissionOnAnyone(org, "ignored");
+ db.users().insertPermissionOnUser(org, user, "ignored");
+ db.users().insertPermissionOnGroup(group1, "ignored");
+ ComponentDto project2 = db.components().insertProject();
+ db.users().insertProjectPermissionOnGroup(group1, "ignored", project2);
+
+ Set<String> permissions = underTest.selectRootComponentPermissionsOfAnonymous(dbSession, project1.getId());
+ assertThat(permissions).containsOnly("perm1");
+
+ // non granted project
+ permissions = underTest.selectRootComponentPermissionsOfAnonymous(dbSession, project2.getId());
+ assertThat(permissions).isEmpty();
+ }
+
+}