import java.util.Collection;
import java.util.List;
import java.util.Set;
+import org.sonar.db.user.GroupDto;
import org.sonar.server.user.UserSession;
/**
return notImplemented();
}
+ @Override
+ public Collection<GroupDto> getGroups() {
+ return notImplemented();
+ }
+
@Override
public Set<String> getUserGroups() {
return notImplemented();
*/
package org.sonar.server.user;
+import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.sonar.api.security.DefaultGroups;
import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.db.user.GroupDto;
/**
* Allow code to be executed with the highest privileges possible, as if executed by a {@link GlobalPermissions#SYSTEM_ADMIN} account.
return null;
}
+ @Override
+ public Collection<GroupDto> getGroups() {
+ return Collections.emptyList();
+ }
+
@Override
public Set<String> getUserGroups() {
return Collections.singleton(DefaultGroups.ANYONE);
*/
package org.sonar.server.user;
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.SetMultimap;
private final UserDto userDto;
private final DbClient dbClient;
private final ResourceDao resourceDao;
- private final Set<String> userGroups;
+ private final Supplier<List<GroupDto>> groups;
private List<String> globalPermissions = null;
private SetMultimap<String, String> projectKeyByPermission = HashMultimap.create();
private SetMultimap<String, String> projectUuidByPermission = HashMultimap.create();
this.userDto = userDto;
this.dbClient = dbClient;
this.resourceDao = dbClient.resourceDao();
- this.userGroups = loadUserGroups();
+ this.groups = Suppliers.memoize(this::loadGroups);
}
public static ServerUserSession createForUser(DbClient dbClient, UserDto userDto) {
return new ServerUserSession(dbClient, null);
}
- private Set<String> loadUserGroups() {
+ private List<GroupDto> loadGroups() {
if (this.userDto == null) {
- return Collections.singleton(DefaultGroups.ANYONE);
+ return Collections.emptyList();
}
try (DbSession dbSession = dbClient.openSession(false)) {
- return Stream.concat(
- Stream.of(DefaultGroups.ANYONE),
- dbClient.groupDao().selectByUserLogin(dbSession, userDto.getLogin()).stream().map(GroupDto::getName))
- .collect(Collectors.toSet());
+ return dbClient.groupDao().selectByUserLogin(dbSession, userDto.getLogin());
}
}
return userDto == null ? null : userDto.getId().intValue();
}
+ @Override
+ public Collection<GroupDto> getGroups() {
+ return groups.get();
+ }
+
@Override
public Set<String> getUserGroups() {
- return userGroups;
+ Collection<GroupDto> groups = getGroups();
+ return Stream.concat(
+ Stream.of(DefaultGroups.ANYONE),
+ groups.stream().map(GroupDto::getName))
+ .collect(Collectors.toSet(groups.size() + 1));
}
@Override
import java.util.List;
import java.util.Set;
import javax.annotation.CheckForNull;
+import org.sonar.db.user.GroupDto;
import org.sonar.server.exceptions.UnauthorizedException;
/**
return get().getUserId();
}
+ @Override
+ public Collection<GroupDto> getGroups() {
+ return get().getGroups();
+ }
+
@Override
public Set<String> getUserGroups() {
return get().getUserGroups();
import java.util.List;
import java.util.Set;
import javax.annotation.CheckForNull;
+import org.sonar.api.security.DefaultGroups;
+import org.sonar.db.user.GroupDto;
public interface UserSession {
@CheckForNull
Integer getUserId();
/**
- * @deprecated does not support organizations as group names are not unique
+ * The groups that the logged-in user is member of. An empty
+ * collection is returned if user is anonymous.
+ */
+ Collection<GroupDto> getGroups();
+
+ /**
+ * The groups that the user is member of, always including
+ * the virtual group named {@link DefaultGroups#ANYONE}.
+ *
+ * @deprecated does not support organizations because group names
+ * are not unique
+ * @see #getGroups()
*/
@Deprecated
Set<String> getUserGroups();
+ /**
+ * Whether the user is logged-in or anonymous.
+ */
boolean isLoggedIn();
boolean isRoot();
.setFileUuid(testFile.uuid())
.setTestData(asList(tests)));
db.commit();
- testIndexer.index(project.uuid());
+ testIndexer.index();
}
private static ListResponse call(TestRequest request) {
*/
package org.sonar.server.tester;
+import java.util.Collection;
+import java.util.Collections;
+import org.sonar.db.user.GroupDto;
+
public class AnonymousMockUserSession extends AbstractMockUserSession<AnonymousMockUserSession> {
public AnonymousMockUserSession() {
return false;
}
+ @Override
+ public Collection<GroupDto> getGroups() {
+ return Collections.emptyList();
+ }
}
*/
package org.sonar.server.tester;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
import java.util.Objects;
+import org.sonar.db.user.GroupDto;
import org.sonar.db.user.UserDto;
import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Arrays.asList;
public class MockUserSession extends AbstractMockUserSession<MockUserSession> {
private final String login;
private boolean root = false;
private Integer userId;
private String name;
+ private List<GroupDto> groups = new ArrayList<>();
public MockUserSession(String login) {
super(MockUserSession.class);
return this;
}
+ @Override
+ public Collection<GroupDto> getGroups() {
+ return groups;
+ }
+
+ public MockUserSession setGroups(GroupDto... groups) {
+ this.groups = asList(groups);
+ return this;
+ }
}
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import org.sonar.db.organization.OrganizationDto;
+import org.sonar.db.user.GroupDto;
import org.sonar.db.user.UserDto;
import org.sonar.server.user.ThreadLocalUserSession;
import org.sonar.server.user.UserSession;
return currentUserSession.getUserId();
}
+ @Override
+ public Collection<GroupDto> getGroups() {
+ return currentUserSession.getGroups();
+ }
+
@Override
public Set<String> getUserGroups() {
return currentUserSession.getUserGroups();
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.ComponentTesting;
import org.sonar.db.organization.OrganizationDto;
+import org.sonar.db.user.GroupDto;
import org.sonar.db.user.UserDto;
import org.sonar.server.exceptions.ForbiddenException;
db.users().insertUser(userDto);
}
+ @Test
+ public void getGroups_is_empty_on_anonymous() {
+ assertThat(newAnonymousSession().getGroups()).isEmpty();
+ }
+
+ @Test
+ public void getGroups_is_empty_if_user_is_not_member_of_any_group() {
+ assertThat(newUserSession(userDto).getGroups()).isEmpty();
+ }
+
+ @Test
+ public void getGroups_returns_the_groups_of_logged_in_user() {
+ GroupDto group1 = db.users().insertGroup();
+ GroupDto group2 = db.users().insertGroup();
+ db.users().insertMember(group1, userDto);
+ db.users().insertMember(group2, userDto);
+
+ assertThat(newUserSession(userDto).getGroups()).extracting(GroupDto::getId).containsOnly(group1.getId(), group2.getId());
+ }
+
+ @Test
+ public void getGroups_keeps_groups_in_cache() {
+ GroupDto group1 = db.users().insertGroup();
+ GroupDto group2 = db.users().insertGroup();
+ db.users().insertMember(group1, userDto);
+
+ ServerUserSession session = newUserSession(userDto);
+ assertThat(session.getGroups()).extracting(GroupDto::getId).containsOnly(group1.getId());
+
+ // membership updated but not cache
+ db.users().insertMember(group2, userDto);
+ assertThat(session.getGroups()).extracting(GroupDto::getId).containsOnly(group1.getId());
+ }
+
@Test
public void isRoot_is_false_is_flag_root_is_false_on_UserDto() {
assertThat(newUserSession(ROOT_USER_DTO).isRoot()).isTrue();
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
+import org.sonar.db.user.GroupDto;
+import org.sonar.db.user.GroupTesting;
import org.sonar.server.exceptions.UnauthorizedException;
-import org.sonar.server.tester.AbstractMockUserSession;
import org.sonar.server.tester.AnonymousMockUserSession;
import org.sonar.server.tester.MockUserSession;
public class ThreadLocalUserSessionTest {
- ThreadLocalUserSession threadLocalUserSession = new ThreadLocalUserSession();
+ private ThreadLocalUserSession threadLocalUserSession = new ThreadLocalUserSession();
@Rule
public ExpectedException thrown = ExpectedException.none();
@Test
public void get_session_for_user() {
- AbstractMockUserSession expected = new MockUserSession("karadoc").setUserId(123);
+ GroupDto group = GroupTesting.newGroupDto();
+ MockUserSession expected = new MockUserSession("karadoc")
+ .setUserId(123)
+ .setGroups(group);
threadLocalUserSession.set(expected);
UserSession session = threadLocalUserSession.get();
assertThat(threadLocalUserSession.getUserId()).isEqualTo(123);
assertThat(threadLocalUserSession.getLogin()).isEqualTo("karadoc");
assertThat(threadLocalUserSession.isLoggedIn()).isTrue();
+ assertThat(threadLocalUserSession.getGroups()).extracting(GroupDto::getId).containsOnly(group.getId());
}
@Test
assertThat(threadLocalUserSession.getLogin()).isNull();
assertThat(threadLocalUserSession.getUserId()).isNull();
assertThat(threadLocalUserSession.isLoggedIn()).isFalse();
+ assertThat(threadLocalUserSession.getGroups()).isEmpty();
}
@Test