org.sonar.server.user.ServerUserSession.java Source code

Java tutorial

Introduction

Here is the source code for org.sonar.server.user.ServerUserSession.java

Source

/*
 * SonarQube
 * Copyright (C) 2009-2017 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 com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableSet;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.sonar.core.permission.ProjectPermissions;
import org.sonar.core.util.stream.MoreCollectors;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.permission.OrganizationPermission;
import org.sonar.db.user.GroupDto;
import org.sonar.db.user.UserDto;
import org.sonar.server.organization.DefaultOrganizationProvider;
import org.sonar.server.organization.OrganizationFlags;

import static com.google.common.collect.Maps.newHashMap;

/**
 * Implementation of {@link UserSession} used in web server
 */
public class ServerUserSession extends AbstractUserSession {
    @CheckForNull
    private final UserDto userDto;
    private final DbClient dbClient;
    private final OrganizationFlags organizationFlags;
    private final DefaultOrganizationProvider defaultOrganizationProvider;
    private final Supplier<Collection<GroupDto>> groups = Suppliers.memoize(this::loadGroups);
    private final Supplier<Boolean> isSystemAdministratorSupplier = Suppliers
            .memoize(this::loadIsSystemAdministrator);
    private final Map<String, String> projectUuidByComponentUuid = newHashMap();
    private Map<String, Set<OrganizationPermission>> permissionsByOrganizationUuid;
    private Map<String, Set<String>> permissionsByProjectUuid;

    ServerUserSession(DbClient dbClient, OrganizationFlags organizationFlags,
            DefaultOrganizationProvider defaultOrganizationProvider, @Nullable UserDto userDto) {
        this.dbClient = dbClient;
        this.organizationFlags = organizationFlags;
        this.defaultOrganizationProvider = defaultOrganizationProvider;
        this.userDto = userDto;
    }

    private Collection<GroupDto> loadGroups() {
        if (this.userDto == null) {
            return Collections.emptyList();
        }
        try (DbSession dbSession = dbClient.openSession(false)) {
            return dbClient.groupDao().selectByUserLogin(dbSession, userDto.getLogin());
        }
    }

    @Override
    @CheckForNull
    public String getLogin() {
        return userDto == null ? null : userDto.getLogin();
    }

    @Override
    @CheckForNull
    public String getName() {
        return userDto == null ? null : userDto.getName();
    }

    @Override
    @CheckForNull
    public Integer getUserId() {
        return userDto == null ? null : userDto.getId();
    }

    @Override
    public Collection<GroupDto> getGroups() {
        return groups.get();
    }

    @Override
    public boolean isLoggedIn() {
        return userDto != null;
    }

    @Override
    public boolean isRoot() {
        return userDto != null && userDto.isRoot();
    }

    @Override
    protected boolean hasPermissionImpl(OrganizationPermission permission, String organizationUuid) {
        if (permissionsByOrganizationUuid == null) {
            permissionsByOrganizationUuid = new HashMap<>();
        }
        Set<OrganizationPermission> permissions = permissionsByOrganizationUuid.computeIfAbsent(organizationUuid,
                this::loadOrganizationPermissions);
        return permissions.contains(permission);
    }

    private Set<OrganizationPermission> loadOrganizationPermissions(String organizationUuid) {
        Set<String> permissionKeys;
        try (DbSession dbSession = dbClient.openSession(false)) {
            if (userDto != null && userDto.getId() != null) {
                permissionKeys = dbClient.authorizationDao().selectOrganizationPermissions(dbSession,
                        organizationUuid, userDto.getId());
            } else {
                permissionKeys = dbClient.authorizationDao().selectOrganizationPermissionsOfAnonymous(dbSession,
                        organizationUuid);
            }
        }
        return permissionKeys.stream().map(OrganizationPermission::fromKey)
                .collect(MoreCollectors.toSet(permissionKeys.size()));
    }

    @Override
    protected Optional<String> componentUuidToProjectUuid(String componentUuid) {
        String projectUuid = projectUuidByComponentUuid.get(componentUuid);
        if (projectUuid != null) {
            return Optional.of(projectUuid);
        }
        try (DbSession dbSession = dbClient.openSession(false)) {
            com.google.common.base.Optional<ComponentDto> component = dbClient.componentDao()
                    .selectByUuid(dbSession, componentUuid);
            if (!component.isPresent()) {
                return Optional.empty();
            }
            projectUuid = component.get().projectUuid();
            projectUuidByComponentUuid.put(componentUuid, projectUuid);
            return Optional.of(projectUuid);
        }
    }

    @Override
    protected boolean hasProjectUuidPermission(String permission, String projectUuid) {
        if (permissionsByProjectUuid == null) {
            permissionsByProjectUuid = new HashMap<>();
        }
        Set<String> permissions = permissionsByProjectUuid.computeIfAbsent(projectUuid,
                this::loadProjectPermissions);
        return permissions.contains(permission);
    }

    private Set<String> loadProjectPermissions(String projectUuid) {
        try (DbSession dbSession = dbClient.openSession(false)) {
            com.google.common.base.Optional<ComponentDto> component = dbClient.componentDao()
                    .selectByUuid(dbSession, projectUuid);
            if (!component.isPresent()) {
                return Collections.emptySet();
            }
            if (component.get().isPrivate()) {
                return loadDbPermissions(dbSession, projectUuid);
            }
            ImmutableSet.Builder<String> builder = ImmutableSet.builder();
            builder.addAll(ProjectPermissions.PUBLIC_PERMISSIONS);
            builder.addAll(loadDbPermissions(dbSession, projectUuid));
            return builder.build();
        }
    }

    private Set<String> loadDbPermissions(DbSession dbSession, String projectUuid) {
        if (userDto != null && userDto.getId() != null) {
            return dbClient.authorizationDao().selectProjectPermissions(dbSession, projectUuid, userDto.getId());
        }
        return dbClient.authorizationDao().selectProjectPermissionsOfAnonymous(dbSession, projectUuid);
    }

    @Override
    protected List<ComponentDto> doKeepAuthorizedComponents(String permission,
            Collection<ComponentDto> components) {
        try (DbSession dbSession = dbClient.openSession(false)) {
            Set<String> projectUuids = components.stream().map(ComponentDto::projectUuid)
                    .collect(MoreCollectors.toSet(components.size()));
            Set<String> authorizedProjectUuids = dbClient.authorizationDao().keepAuthorizedProjectUuids(dbSession,
                    projectUuids, getUserId(), permission);

            return components.stream().filter(c -> authorizedProjectUuids.contains(c.projectUuid()))
                    .collect(MoreCollectors.toList(components.size()));
        }
    }

    @Override
    public boolean isSystemAdministrator() {
        return isSystemAdministratorSupplier.get();
    }

    private boolean loadIsSystemAdministrator() {
        if (isRoot()) {
            return true;
        }
        try (DbSession dbSession = dbClient.openSession(false)) {
            if (!organizationFlags.isEnabled(dbSession)) {
                String uuidOfDefaultOrg = defaultOrganizationProvider.get().getUuid();
                return hasPermission(OrganizationPermission.ADMINISTER, uuidOfDefaultOrg);
            }
            // organization feature is enabled -> requires to be root
            return false;
        }
    }
}