]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-11036 add WS api/alm_integration/list_repositories
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Mon, 23 Jul 2018 07:56:42 +0000 (09:56 +0200)
committerSonarTech <sonartech@sonarsource.com>
Fri, 10 Aug 2018 18:21:28 +0000 (20:21 +0200)
server/sonar-server/src/main/java/org/sonar/server/authentication/SafeModeUserSession.java
server/sonar-server/src/main/java/org/sonar/server/user/AbstractUserSession.java
server/sonar-server/src/main/java/org/sonar/server/user/DoPrivileged.java
server/sonar-server/src/main/java/org/sonar/server/user/ServerUserSession.java
server/sonar-server/src/main/java/org/sonar/server/user/ThreadLocalUserSession.java
server/sonar-server/src/main/java/org/sonar/server/user/UserSession.java
server/sonar-server/src/test/java/org/sonar/server/tester/AnonymousMockUserSession.java
server/sonar-server/src/test/java/org/sonar/server/tester/MockUserSession.java
server/sonar-server/src/test/java/org/sonar/server/tester/UserSessionRule.java
server/sonar-server/src/test/java/org/sonar/server/user/TestUserSessionFactory.java

index 3660f91d871f567815f6a5a989e5a7b787fe077e..b4bc28aed761accc1b887f95132c43d01a34a7a7 100644 (file)
@@ -81,6 +81,16 @@ public class SafeModeUserSession extends AbstractUserSession {
     return Collections.emptyList();
   }
 
+  @Override
+  public Optional<IdentityProvider> getIdentityProvider() {
+    return Optional.empty();
+  }
+
+  @Override
+  public Optional<ExternalIdentity> getExternalIdentity() {
+    return Optional.empty();
+  }
+
   @Override
   public boolean isLoggedIn() {
     return false;
index 1bc20879f51997dfe28db80cfe1ea17a0e9a0d13..2a92147ee5929b77aac30dff21291b4f72db4ae8 100644 (file)
@@ -23,11 +23,14 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 import java.util.Optional;
+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.component.ComponentDto;
 import org.sonar.db.organization.OrganizationDto;
 import org.sonar.db.permission.OrganizationPermission;
+import org.sonar.db.user.UserDto;
 import org.sonar.server.exceptions.ForbiddenException;
 import org.sonar.server.exceptions.UnauthorizedException;
 
@@ -38,6 +41,49 @@ public abstract class AbstractUserSession implements UserSession {
   private static final String INSUFFICIENT_PRIVILEGES_MESSAGE = "Insufficient privileges";
   private static final ForbiddenException INSUFFICIENT_PRIVILEGES_EXCEPTION = new ForbiddenException(INSUFFICIENT_PRIVILEGES_MESSAGE);
   private static final String AUTHENTICATION_IS_REQUIRED_MESSAGE = "Authentication is required";
+
+  protected static Identity computeIdentity(UserDto userDto) {
+    switch (userDto.getExternalIdentityProvider()) {
+      case "github":
+        return new Identity(IdentityProvider.GITHUB, externalIdentityOf(userDto));
+      case "bitbucket":
+        return new Identity(IdentityProvider.BITBUCKET, externalIdentityOf(userDto));
+      case "sonarqube":
+        return new Identity(IdentityProvider.SONARQUBE, null);
+      default:
+        return new Identity(IdentityProvider.OTHER, externalIdentityOf(userDto));
+    }
+  }
+
+  @CheckForNull
+  private static ExternalIdentity externalIdentityOf(UserDto userDto) {
+    String externalId = userDto.getExternalId();
+    String externalLogin = userDto.getExternalLogin();
+    if (externalId == null && externalLogin == null) {
+      return null;
+    }
+    return new ExternalIdentity(externalId == null ? externalLogin : externalId, externalLogin);
+  }
+
+  protected static final class Identity {
+    private final IdentityProvider identityProvider;
+    private final ExternalIdentity externalIdentity;
+
+    private Identity(IdentityProvider identityProvider, @Nullable ExternalIdentity externalIdentity) {
+      this.identityProvider = identityProvider;
+      this.externalIdentity = externalIdentity;
+    }
+
+    public IdentityProvider getIdentityProvider() {
+      return identityProvider;
+    }
+
+    @CheckForNull
+    public ExternalIdentity getExternalIdentity() {
+      return externalIdentity;
+    }
+  }
+
   @Override
   public final boolean hasPermission(OrganizationPermission permission, OrganizationDto organization) {
     return hasPermission(permission, organization.getUuid());
index 434d3731e85d92f2e090b65ab9798e0ad3acb831..e86febc71fb9fe37accd2c79bb28fdf05c61167a 100644 (file)
@@ -102,6 +102,16 @@ public final class DoPrivileged {
         return true;
       }
 
+      @Override
+      public Optional<IdentityProvider> getIdentityProvider() {
+        return Optional.empty();
+      }
+
+      @Override
+      public Optional<ExternalIdentity> getExternalIdentity() {
+        return Optional.empty();
+      }
+
       @Override
       protected boolean hasPermissionImpl(OrganizationPermission permission, String organizationUuid) {
         return true;
index e366d1713da747563852428d92e13a927b01df6a..8bf2423859b78dc190c80d876b3f84afc44ae14a 100644 (file)
@@ -46,6 +46,8 @@ import org.sonar.server.organization.DefaultOrganizationProvider;
 import org.sonar.server.organization.OrganizationFlags;
 
 import static java.util.Objects.requireNonNull;
+import static java.util.Optional.of;
+import static java.util.Optional.ofNullable;
 import static org.apache.commons.lang.StringUtils.defaultIfEmpty;
 
 /**
@@ -120,6 +122,16 @@ public class ServerUserSession extends AbstractUserSession {
     return userDto != null && userDto.isRoot();
   }
 
+  @Override
+  public Optional<IdentityProvider> getIdentityProvider() {
+    return ofNullable(userDto).map(d -> computeIdentity(d).getIdentityProvider());
+  }
+
+  @Override
+  public Optional<ExternalIdentity> getExternalIdentity() {
+    return ofNullable(userDto).map(d -> computeIdentity(d).getExternalIdentity());
+  }
+
   @Override
   protected boolean hasPermissionImpl(OrganizationPermission permission, String organizationUuid) {
     if (permissionsByOrganizationUuid == null) {
@@ -147,7 +159,7 @@ public class ServerUserSession extends AbstractUserSession {
   protected Optional<String> componentUuidToProjectUuid(String componentUuid) {
     String projectUuid = projectUuidByComponentUuid.get(componentUuid);
     if (projectUuid != null) {
-      return Optional.of(projectUuid);
+      return of(projectUuid);
     }
     try (DbSession dbSession = dbClient.openSession(false)) {
       com.google.common.base.Optional<ComponentDto> component = dbClient.componentDao().selectByUuid(dbSession, componentUuid);
@@ -158,7 +170,7 @@ public class ServerUserSession extends AbstractUserSession {
       // checked on the project (represented by its main branch)
       projectUuid = defaultIfEmpty(component.get().getMainBranchProjectUuid(), component.get().projectUuid());
       projectUuidByComponentUuid.put(componentUuid, projectUuid);
-      return Optional.of(projectUuid);
+      return of(projectUuid);
     }
   }
 
index 8b7fb1b6ee26896d504ae70be2c4e02ce7cd3e3a..9b4e09ac4a2bf3d709d4f49ab87dcc76d02af8fe 100644 (file)
@@ -21,6 +21,7 @@ package org.sonar.server.user;
 
 import java.util.Collection;
 import java.util.List;
+import java.util.Optional;
 import javax.annotation.CheckForNull;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.organization.OrganizationDto;
@@ -84,6 +85,16 @@ public class ThreadLocalUserSession implements UserSession {
     return get().getGroups();
   }
 
+  @Override
+  public Optional<IdentityProvider> getIdentityProvider() {
+    return get().getIdentityProvider();
+  }
+
+  @Override
+  public Optional<ExternalIdentity> getExternalIdentity() {
+    return get().getExternalIdentity();
+  }
+
   @Override
   public boolean isLoggedIn() {
     return get().isLoggedIn();
index 645254afcf3219f775e9b3dceab4e3450ad7ed4e..56a41cc39cb80e15933fa536f2c22c17fc180c5f 100644 (file)
@@ -21,12 +21,17 @@ package org.sonar.server.user;
 
 import java.util.Collection;
 import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
 import javax.annotation.CheckForNull;
+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.user.GroupDto;
 
+import static java.util.Objects.requireNonNull;
+
 public interface UserSession {
 
   /**
@@ -63,6 +68,68 @@ public interface UserSession {
    */
   Collection<GroupDto> getGroups();
 
+  /**
+   * This enum supports by name only the few providers for which specific code exists.
+   */
+  enum IdentityProvider {
+    SONARQUBE, GITHUB, BITBUCKET, OTHER
+  }
+
+  /**
+   * @return empty if user is anonymous
+   */
+  Optional<IdentityProvider> getIdentityProvider();
+
+  @Immutable
+  final class ExternalIdentity {
+    private final String id;
+    private final String login;
+
+    public ExternalIdentity(String id, String login) {
+      this.id = requireNonNull(id, "id can't be null");
+      this.login = requireNonNull(login, "login can't be null");
+    }
+
+    public String getId() {
+      return id;
+    }
+
+    public String getLogin() {
+      return login;
+    }
+
+    @Override
+    public String toString() {
+      return "ExternalIdentity{" +
+        "id='" + id + '\'' +
+        ", login='" + login + '\'' +
+        '}';
+    }
+
+    @Override
+    public boolean equals(Object o) {
+      if (this == o) {
+        return true;
+      }
+      if (o == null || getClass() != o.getClass()) {
+        return false;
+      }
+      ExternalIdentity that = (ExternalIdentity) o;
+      return Objects.equals(id, that.id) &&
+        Objects.equals(login, that.login);
+    }
+
+    @Override
+    public int hashCode() {
+      return Objects.hash(id, login);
+    }
+  }
+
+  /**
+   * @return empty if {@link #getIdentityProvider()} returns empty or {@link IdentityProvider#SONARQUBE}
+   */
+  Optional<ExternalIdentity> getExternalIdentity();
+
   /**
    * Whether the user is logged-in or anonymous.
    */
index e080df152cc888189cc0f48382925bc37ed597f3..c7ec3312f6feca67c8d76d1186dc6a67ae6ac584 100644 (file)
@@ -21,6 +21,7 @@ package org.sonar.server.tester;
 
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Optional;
 import org.sonar.db.organization.OrganizationDto;
 import org.sonar.db.user.GroupDto;
 
@@ -64,6 +65,16 @@ public class AnonymousMockUserSession extends AbstractMockUserSession<AnonymousM
     return Collections.emptyList();
   }
 
+  @Override
+  public Optional<IdentityProvider> getIdentityProvider() {
+    return Optional.empty();
+  }
+
+  @Override
+  public Optional<ExternalIdentity> getExternalIdentity() {
+    return Optional.empty();
+  }
+
   @Override
   public boolean hasMembershipImpl(OrganizationDto organizationDto) {
     return false;
index 91afb2ea4dd9a3d0be560daac04aa87663e18a33..851fdb97a324174302cd471164dea3a4911493ca 100644 (file)
@@ -22,12 +22,15 @@ package org.sonar.server.tester;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
-import java.util.Objects;
+import java.util.Optional;
 import org.sonar.db.user.GroupDto;
 import org.sonar.db.user.UserDto;
+import org.sonar.server.user.AbstractUserSession;
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static java.util.Arrays.asList;
+import static java.util.Objects.requireNonNull;
+import static org.sonar.server.user.UserSession.IdentityProvider.SONARQUBE;
 
 public class MockUserSession extends AbstractMockUserSession<MockUserSession> {
   private final String login;
@@ -36,6 +39,8 @@ public class MockUserSession extends AbstractMockUserSession<MockUserSession> {
   private Integer userId;
   private String name;
   private List<GroupDto> groups = new ArrayList<>();
+  private IdentityProvider identityProvider;
+  private ExternalIdentity externalIdentity;
 
   public MockUserSession(String login) {
     super(MockUserSession.class);
@@ -44,6 +49,7 @@ public class MockUserSession extends AbstractMockUserSession<MockUserSession> {
     setUuid(login + "uuid");
     setUserId(login.hashCode());
     setName(login + " name");
+    setInternalIdentity();
   }
 
   public MockUserSession(UserDto userDto) {
@@ -53,6 +59,9 @@ public class MockUserSession extends AbstractMockUserSession<MockUserSession> {
     setUuid(userDto.getUuid());
     setUserId(userDto.getId());
     setName(userDto.getName());
+    AbstractUserSession.Identity identity = computeIdentity(userDto);
+    this.identityProvider = identity.getIdentityProvider();
+    this.externalIdentity = identity.getExternalIdentity();
   }
 
   @Override
@@ -80,7 +89,7 @@ public class MockUserSession extends AbstractMockUserSession<MockUserSession> {
   }
 
   public MockUserSession setUuid(String uuid) {
-    this.uuid = Objects.requireNonNull(uuid);
+    this.uuid = requireNonNull(uuid);
     return this;
   }
 
@@ -90,7 +99,7 @@ public class MockUserSession extends AbstractMockUserSession<MockUserSession> {
   }
 
   public MockUserSession setName(String s) {
-    this.name = Objects.requireNonNull(s);
+    this.name = requireNonNull(s);
     return this;
   }
 
@@ -114,4 +123,24 @@ public class MockUserSession extends AbstractMockUserSession<MockUserSession> {
     return this;
   }
 
+  @Override
+  public Optional<IdentityProvider> getIdentityProvider() {
+    return Optional.ofNullable(identityProvider);
+  }
+
+  public void setExternalIdentity(IdentityProvider identityProvider, ExternalIdentity externalIdentity) {
+    checkArgument(identityProvider != SONARQUBE);
+    this.identityProvider = identityProvider;
+    this.externalIdentity = requireNonNull(externalIdentity);
+  }
+
+  public void setInternalIdentity() {
+    this.identityProvider = SONARQUBE;
+    this.externalIdentity = null;
+  }
+
+  @Override
+  public Optional<ExternalIdentity> getExternalIdentity() {
+    return Optional.ofNullable(externalIdentity);
+  }
 }
index a3df41abed9993846427f947589ef76d21c3ebf1..8a54d0e919d9b20113dc5a2739a859f24e9f6d42 100644 (file)
@@ -22,6 +22,7 @@ package org.sonar.server.tester;
 import com.google.common.base.Preconditions;
 import java.util.Collection;
 import java.util.List;
+import java.util.Optional;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
 import org.junit.rules.TestRule;
@@ -138,6 +139,16 @@ public class UserSessionRule implements TestRule, UserSession {
     return this;
   }
 
+  public UserSessionRule setExternalIdentity(IdentityProvider identityProvider, ExternalIdentity externalIdentity) {
+    ensureMockUserSession().setExternalIdentity(identityProvider, externalIdentity);
+    return this;
+  }
+
+  public UserSessionRule setInternalIdentity() {
+    ensureMockUserSession().setInternalIdentity();
+    return this;
+  }
+
   @Override
   public Statement apply(Statement statement, Description description) {
     return this.statement(statement);
@@ -268,6 +279,16 @@ public class UserSessionRule implements TestRule, UserSession {
     return currentUserSession.getGroups();
   }
 
+  @Override
+  public Optional<IdentityProvider> getIdentityProvider() {
+    return currentUserSession.getIdentityProvider();
+  }
+
+  @Override
+  public Optional<ExternalIdentity> getExternalIdentity() {
+    return currentUserSession.getExternalIdentity();
+  }
+
   @Override
   public boolean isLoggedIn() {
     return currentUserSession.isLoggedIn();
index 7b055ab52a2924e5e0ad866d3aa4c8fac53f4f41..dd1cb95c44096d47fbd1cb60070af140563ed1b6 100644 (file)
@@ -87,6 +87,16 @@ public class TestUserSessionFactory implements UserSessionFactory {
       throw notImplemented();
     }
 
+    @Override
+    public Optional<IdentityProvider> getIdentityProvider() {
+      throw notImplemented();
+    }
+
+    @Override
+    public Optional<ExternalIdentity> getExternalIdentity() {
+      throw notImplemented();
+    }
+
     @Override
     public boolean isLoggedIn() {
       return user != null;