diff options
author | Duarte Meneses <duarte.meneses@sonarsource.com> | 2019-10-23 15:33:39 -0500 |
---|---|---|
committer | SonarTech <sonartech@sonarsource.com> | 2020-01-31 20:46:09 +0100 |
commit | ace9a50d55d831ec71b7db421aa04d1198392c6c (patch) | |
tree | 3bf598bfe3f760d45310b2a65d014a53370a9930 /server/sonar-webserver-auth | |
parent | 1ff9a01fd6e822793ef223f9ce259b15d17eecc4 (diff) | |
download | sonarqube-ace9a50d55d831ec71b7db421aa04d1198392c6c.tar.gz sonarqube-ace9a50d55d831ec71b7db421aa04d1198392c6c.zip |
SONAR-12689 Separate storage of projects/apps from their components and branches
Diffstat (limited to 'server/sonar-webserver-auth')
6 files changed, 111 insertions, 2 deletions
diff --git a/server/sonar-webserver-auth/src/main/java/org/sonar/server/user/AbstractUserSession.java b/server/sonar-webserver-auth/src/main/java/org/sonar/server/user/AbstractUserSession.java index 5689072bc1c..8ba3e53e1fc 100644 --- a/server/sonar-webserver-auth/src/main/java/org/sonar/server/user/AbstractUserSession.java +++ b/server/sonar-webserver-auth/src/main/java/org/sonar/server/user/AbstractUserSession.java @@ -32,6 +32,7 @@ import org.sonar.core.util.stream.MoreCollectors; import org.sonar.db.component.ComponentDto; import org.sonar.db.organization.OrganizationDto; import org.sonar.db.permission.OrganizationPermission; +import org.sonar.db.project.ProjectDto; import org.sonar.db.user.UserDto; import org.sonar.server.exceptions.ForbiddenException; import org.sonar.server.exceptions.UnauthorizedException; @@ -98,6 +99,14 @@ public abstract class AbstractUserSession implements UserSession { } @Override + public final boolean hasProjectPermission(String permission, ProjectDto project) { + if (isRoot()) { + return true; + } + return hasProjectUuidPermission(permission, project.getUuid()); + } + + @Override public final boolean hasComponentUuidPermission(String permission, String componentUuid) { if (isRoot()) { return true; @@ -127,6 +136,24 @@ public abstract class AbstractUserSession implements UserSession { return doKeepAuthorizedComponents(permission, components); } + @Override + public List<ProjectDto> keepAuthorizedProjects(String permission, Collection<ProjectDto> projects) { + if (isRoot()) { + return new ArrayList<>(projects); + } + return doKeepAuthorizedProjects(permission, projects); + } + + /** + * Naive implementation, to be overridden if needed + */ + protected List<ProjectDto> doKeepAuthorizedProjects(String permission, Collection<ProjectDto> projects) { + boolean allowPublicComponent = PUBLIC_PERMISSIONS.contains(permission); + return projects.stream() + .filter(c -> (allowPublicComponent && !c.isPrivate()) || hasProjectPermission(permission, c)) + .collect(MoreCollectors.toList()); + } + /** * Naive implementation, to be overridden if needed */ @@ -174,6 +201,14 @@ public abstract class AbstractUserSession implements UserSession { return this; } + @Override public UserSession checkProjectPermission(String projectPermission, ProjectDto project) { + if (isRoot() || hasProjectUuidPermission(projectPermission, project.getUuid())) { + return this; + } + + throw new ForbiddenException(INSUFFICIENT_PRIVILEGES_MESSAGE); + } + @Override public final UserSession checkComponentUuidPermission(String permission, String componentUuid) { if (!hasComponentUuidPermission(permission, componentUuid)) { diff --git a/server/sonar-webserver-auth/src/main/java/org/sonar/server/user/ServerUserSession.java b/server/sonar-webserver-auth/src/main/java/org/sonar/server/user/ServerUserSession.java index 1fbbe17116f..c62055870d6 100644 --- a/server/sonar-webserver-auth/src/main/java/org/sonar/server/user/ServerUserSession.java +++ b/server/sonar-webserver-auth/src/main/java/org/sonar/server/user/ServerUserSession.java @@ -183,6 +183,9 @@ public class ServerUserSession extends AbstractUserSession { return permissions.contains(permission); } + /** + * Also applies to views + */ private Set<String> loadProjectPermissions(String projectUuid) { try (DbSession dbSession = dbClient.openSession(false)) { Optional<ComponentDto> component = dbClient.componentDao().selectByUuid(dbSession, projectUuid); diff --git a/server/sonar-webserver-auth/src/main/java/org/sonar/server/user/ThreadLocalUserSession.java b/server/sonar-webserver-auth/src/main/java/org/sonar/server/user/ThreadLocalUserSession.java index 771a434cc23..d310e17dd1c 100644 --- a/server/sonar-webserver-auth/src/main/java/org/sonar/server/user/ThreadLocalUserSession.java +++ b/server/sonar-webserver-auth/src/main/java/org/sonar/server/user/ThreadLocalUserSession.java @@ -26,6 +26,7 @@ import javax.annotation.CheckForNull; import org.sonar.db.component.ComponentDto; import org.sonar.db.organization.OrganizationDto; import org.sonar.db.permission.OrganizationPermission; +import org.sonar.db.project.ProjectDto; import org.sonar.db.user.GroupDto; import org.sonar.server.exceptions.UnauthorizedException; @@ -134,6 +135,12 @@ public class ThreadLocalUserSession implements UserSession { } @Override + public UserSession checkProjectPermission(String projectPermission, ProjectDto project) { + get().checkProjectPermission(projectPermission, project); + return this; + } + + @Override public UserSession checkComponentUuidPermission(String permission, String componentUuid) { get().checkComponentUuidPermission(permission, componentUuid); return this; @@ -155,6 +162,10 @@ public class ThreadLocalUserSession implements UserSession { return get().hasComponentPermission(permission, component); } + @Override public boolean hasProjectPermission(String permission, ProjectDto project) { + return get().hasProjectPermission(permission, project); + } + @Override public boolean hasComponentUuidPermission(String permission, String componentUuid) { return get().hasComponentUuidPermission(permission, componentUuid); @@ -176,6 +187,10 @@ public class ThreadLocalUserSession implements UserSession { return get().keepAuthorizedComponents(permission, components); } + @Override public List<ProjectDto> keepAuthorizedProjects(String permission, Collection<ProjectDto> projects) { + return get().keepAuthorizedProjects(permission, projects); + } + @Override public boolean hasMembership(OrganizationDto organizationDto) { return get().hasMembership(organizationDto); diff --git a/server/sonar-webserver-auth/src/main/java/org/sonar/server/user/UserSession.java b/server/sonar-webserver-auth/src/main/java/org/sonar/server/user/UserSession.java index 7fb907e4b9b..6c160f26a71 100644 --- a/server/sonar-webserver-auth/src/main/java/org/sonar/server/user/UserSession.java +++ b/server/sonar-webserver-auth/src/main/java/org/sonar/server/user/UserSession.java @@ -29,6 +29,7 @@ import javax.annotation.concurrent.Immutable; import org.sonar.db.component.ComponentDto; import org.sonar.db.organization.OrganizationDto; import org.sonar.db.permission.OrganizationPermission; +import org.sonar.db.project.ProjectDto; import org.sonar.db.user.GroupDto; import static java.util.Objects.requireNonNull; @@ -98,8 +99,7 @@ public interface UserSession { */ Optional<IdentityProvider> getIdentityProvider(); - @Immutable - final class ExternalIdentity { + @Immutable final class ExternalIdentity { private final String id; private final String login; @@ -206,6 +206,8 @@ public interface UserSession { */ boolean hasComponentPermission(String permission, ComponentDto component); + boolean hasProjectPermission(String permission, ProjectDto project); + /** * Using {@link #hasComponentPermission(String, ComponentDto)} is recommended * because it does not have to load project if the referenced component @@ -225,6 +227,7 @@ public interface UserSession { */ List<ComponentDto> keepAuthorizedComponents(String permission, Collection<ComponentDto> components); + List<ProjectDto> keepAuthorizedProjects(String permission, Collection<ProjectDto> projects); /** * Ensures that {@link #hasComponentPermission(String, ComponentDto)} is {@code true}, * otherwise throws a {@link org.sonar.server.exceptions.ForbiddenException}. @@ -232,6 +235,12 @@ public interface UserSession { UserSession checkComponentPermission(String projectPermission, ComponentDto component); /** + * Ensures that {@link #hasProjectPermission(String, ProjectDto)} is {@code true}, + * otherwise throws a {@link org.sonar.server.exceptions.ForbiddenException}. + */ + UserSession checkProjectPermission(String projectPermission, ProjectDto project); + + /** * Ensures that {@link #hasComponentUuidPermission(String, String)} is {@code true}, * otherwise throws a {@link org.sonar.server.exceptions.ForbiddenException}. * diff --git a/server/sonar-webserver-auth/src/testFixtures/java/org/sonar/server/tester/AbstractMockUserSession.java b/server/sonar-webserver-auth/src/testFixtures/java/org/sonar/server/tester/AbstractMockUserSession.java index 22e9e3ab9c5..00968fe8362 100644 --- a/server/sonar-webserver-auth/src/testFixtures/java/org/sonar/server/tester/AbstractMockUserSession.java +++ b/server/sonar-webserver-auth/src/testFixtures/java/org/sonar/server/tester/AbstractMockUserSession.java @@ -31,6 +31,7 @@ import org.sonar.api.web.UserRole; import org.sonar.db.component.ComponentDto; import org.sonar.db.organization.OrganizationDto; import org.sonar.db.permission.OrganizationPermission; +import org.sonar.db.project.ProjectDto; import org.sonar.server.user.AbstractUserSession; import static com.google.common.base.Preconditions.checkArgument; @@ -78,6 +79,20 @@ public abstract class AbstractMockUserSession<T extends AbstractMockUserSession> return clazz.cast(this); } + public T registerProjects(ProjectDto... projects) { + Arrays.stream(projects) + .forEach(project -> { + if (!project.isPrivate()) { + this.projectUuidByPermission.put(UserRole.USER, project.getUuid()); + this.projectUuidByPermission.put(UserRole.CODEVIEWER, project.getUuid()); + this.projectPermissions.add(UserRole.USER); + this.projectPermissions.add(UserRole.CODEVIEWER); + } + this.projectUuidByComponentUuid.put(project.getUuid(), project.getUuid()); + }); + return clazz.cast(this); + } + public T addProjectPermission(String permission, ComponentDto... components) { Arrays.stream(components).forEach(component -> { checkArgument( @@ -91,6 +106,19 @@ public abstract class AbstractMockUserSession<T extends AbstractMockUserSession> return clazz.cast(this); } + public T addProjectPermission(String permission, ProjectDto... projects) { + Arrays.stream(projects).forEach(component -> { + checkArgument( + component.isPrivate() || !PUBLIC_PERMISSIONS.contains(permission), + "public component %s can't be granted public permission %s", component.getUuid(), permission); + }); + registerProjects(projects); + this.projectPermissions.add(permission); + Arrays.stream(projects) + .forEach(component -> this.projectUuidByPermission.put(permission, component.getUuid())); + return clazz.cast(this); + } + @Override protected Optional<String> componentUuidToProjectUuid(String componentUuid) { return Optional.ofNullable(projectUuidByComponentUuid.get(componentUuid)); diff --git a/server/sonar-webserver-auth/src/testFixtures/java/org/sonar/server/tester/UserSessionRule.java b/server/sonar-webserver-auth/src/testFixtures/java/org/sonar/server/tester/UserSessionRule.java index c72088db1ae..e243f3870d4 100644 --- a/server/sonar-webserver-auth/src/testFixtures/java/org/sonar/server/tester/UserSessionRule.java +++ b/server/sonar-webserver-auth/src/testFixtures/java/org/sonar/server/tester/UserSessionRule.java @@ -31,6 +31,7 @@ import org.junit.runners.model.Statement; import org.sonar.db.component.ComponentDto; import org.sonar.db.organization.OrganizationDto; import org.sonar.db.permission.OrganizationPermission; +import org.sonar.db.project.ProjectDto; import org.sonar.db.user.GroupDto; import org.sonar.db.user.UserDto; import org.sonar.server.user.UserSession; @@ -192,6 +193,11 @@ public class UserSessionRule implements TestRule, UserSession { return this; } + public UserSessionRule addProjectPermission(String projectPermission, ProjectDto projectDto) { + ensureAbstractMockUserSession().addProjectPermission(projectPermission, projectDto); + return this; + } + public UserSessionRule addPermission(OrganizationPermission permission, String organizationUuid) { ensureAbstractMockUserSession().addPermission(permission, organizationUuid); return this; @@ -240,6 +246,10 @@ public class UserSessionRule implements TestRule, UserSession { return currentUserSession.hasComponentPermission(permission, component); } + @Override public boolean hasProjectPermission(String permission, ProjectDto project) { + return currentUserSession.hasProjectPermission(permission, project); + } + @Override public boolean hasComponentUuidPermission(String permission, String componentUuid) { return currentUserSession.hasComponentUuidPermission(permission, componentUuid); @@ -250,6 +260,10 @@ public class UserSessionRule implements TestRule, UserSession { return currentUserSession.keepAuthorizedComponents(permission, components); } + @Override public List<ProjectDto> keepAuthorizedProjects(String permission, Collection<ProjectDto> projects) { + return currentUserSession.keepAuthorizedProjects(permission, projects); + } + @Override @CheckForNull public String getLogin() { @@ -338,6 +352,11 @@ public class UserSessionRule implements TestRule, UserSession { return this; } + @Override public UserSession checkProjectPermission(String projectPermission, ProjectDto project) { + currentUserSession.checkProjectPermission(projectPermission, project); + return this; + } + @Override public UserSession checkComponentUuidPermission(String permission, String componentUuid) { currentUserSession.checkComponentUuidPermission(permission, componentUuid); |