throw notImplemented();
}
+ @Override
+ public boolean isSystemAdministrator() {
+ throw notImplemented();
+ }
+
+ @Override
+ public UserSession checkIsSystemAdministrator() {
+ throw notImplemented();
+ }
+
@Override
public boolean hasComponentPermission(String permission, ComponentDto component) {
throw notImplemented();
import org.sonar.api.platform.Server;
import org.sonar.api.server.authentication.BaseIdentityProvider;
import org.sonar.api.server.authentication.UserIdentity;
-import org.sonar.db.DbClient;
import org.sonar.db.user.UserDto;
-import org.sonar.server.user.ServerUserSession;
import org.sonar.server.user.ThreadLocalUserSession;
+import org.sonar.server.user.UserSessionFactory;
import static org.sonar.server.authentication.event.AuthenticationEvent.Source;
public class BaseContextFactory {
- private final DbClient dbClient;
private final ThreadLocalUserSession threadLocalUserSession;
private final UserIdentityAuthenticator userIdentityAuthenticator;
private final Server server;
private final JwtHttpHandler jwtHttpHandler;
+ private final UserSessionFactory userSessionFactory;
- public BaseContextFactory(DbClient dbClient, UserIdentityAuthenticator userIdentityAuthenticator, Server server, JwtHttpHandler jwtHttpHandler,
- ThreadLocalUserSession threadLocalUserSession) {
- this.dbClient = dbClient;
+ public BaseContextFactory(UserIdentityAuthenticator userIdentityAuthenticator, Server server, JwtHttpHandler jwtHttpHandler,
+ ThreadLocalUserSession threadLocalUserSession, UserSessionFactory userSessionFactory) {
+ this.userSessionFactory = userSessionFactory;
this.userIdentityAuthenticator = userIdentityAuthenticator;
this.server = server;
this.jwtHttpHandler = jwtHttpHandler;
public void authenticate(UserIdentity userIdentity) {
UserDto userDto = userIdentityAuthenticator.authenticate(userIdentity, identityProvider, Source.external(identityProvider));
jwtHttpHandler.generateToken(userDto, request, response);
- threadLocalUserSession.set(ServerUserSession.createForUser(dbClient, userDto));
+ threadLocalUserSession.set(userSessionFactory.create(userDto));
}
}
}
import org.sonar.api.server.authentication.OAuth2IdentityProvider;
import org.sonar.api.server.authentication.UserIdentity;
import org.sonar.api.utils.MessageException;
-import org.sonar.db.DbClient;
import org.sonar.db.user.UserDto;
import org.sonar.server.authentication.event.AuthenticationEvent;
-import org.sonar.server.user.ServerUserSession;
import org.sonar.server.user.ThreadLocalUserSession;
+import org.sonar.server.user.UserSessionFactory;
import static java.lang.String.format;
import static org.sonar.api.CoreProperties.SERVER_BASE_URL;
public class OAuth2ContextFactory {
- private final DbClient dbClient;
private final ThreadLocalUserSession threadLocalUserSession;
private final UserIdentityAuthenticator userIdentityAuthenticator;
private final Server server;
private final OAuthCsrfVerifier csrfVerifier;
private final JwtHttpHandler jwtHttpHandler;
+ private final UserSessionFactory userSessionFactory;
- public OAuth2ContextFactory(DbClient dbClient, ThreadLocalUserSession threadLocalUserSession, UserIdentityAuthenticator userIdentityAuthenticator, Server server,
- OAuthCsrfVerifier csrfVerifier, JwtHttpHandler jwtHttpHandler) {
- this.dbClient = dbClient;
+ public OAuth2ContextFactory(ThreadLocalUserSession threadLocalUserSession, UserIdentityAuthenticator userIdentityAuthenticator, Server server,
+ OAuthCsrfVerifier csrfVerifier, JwtHttpHandler jwtHttpHandler, UserSessionFactory userSessionFactory) {
this.threadLocalUserSession = threadLocalUserSession;
this.userIdentityAuthenticator = userIdentityAuthenticator;
this.server = server;
this.csrfVerifier = csrfVerifier;
this.jwtHttpHandler = jwtHttpHandler;
+ this.userSessionFactory = userSessionFactory;
}
public OAuth2IdentityProvider.InitContext newContext(HttpServletRequest request, HttpServletResponse response, OAuth2IdentityProvider identityProvider) {
public void authenticate(UserIdentity userIdentity) {
UserDto userDto = userIdentityAuthenticator.authenticate(userIdentity, identityProvider, AuthenticationEvent.Source.oauth2(identityProvider));
jwtHttpHandler.generateToken(userDto, request, response);
- threadLocalUserSession.set(ServerUserSession.createForUser(dbClient, userDto));
+ threadLocalUserSession.set(userSessionFactory.create(userDto));
}
}
}
import javax.servlet.http.HttpServletResponse;
import org.sonar.api.config.Settings;
import org.sonar.api.server.ServerSide;
-import org.sonar.db.DbClient;
import org.sonar.db.user.UserDto;
import org.sonar.server.authentication.event.AuthenticationEvent;
import org.sonar.server.authentication.event.AuthenticationException;
-import org.sonar.server.user.ServerUserSession;
import org.sonar.server.user.ThreadLocalUserSession;
+import org.sonar.server.user.UserSession;
+import org.sonar.server.user.UserSessionFactory;
import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED;
import static org.sonar.api.CoreProperties.CORE_FORCE_AUTHENTICATION_PROPERTY;
import static org.sonar.server.authentication.ws.LoginAction.LOGIN_URL;
import static org.sonar.server.authentication.ws.LogoutAction.LOGOUT_URL;
import static org.sonar.server.authentication.ws.ValidateAction.VALIDATE_URL;
-import static org.sonar.server.user.ServerUserSession.createForAnonymous;
-import static org.sonar.server.user.ServerUserSession.createForUser;
@ServerSide
public class UserSessionInitializer {
.excludes(SKIPPED_URLS)
.build();
- private final DbClient dbClient;
private final Settings settings;
private final JwtHttpHandler jwtHttpHandler;
private final BasicAuthenticator basicAuthenticator;
private final SsoAuthenticator ssoAuthenticator;
private final ThreadLocalUserSession threadLocalSession;
private final AuthenticationEvent authenticationEvent;
+ private final UserSessionFactory userSessionFactory;
- public UserSessionInitializer(DbClient dbClient, Settings settings, JwtHttpHandler jwtHttpHandler, BasicAuthenticator basicAuthenticator,
- SsoAuthenticator ssoAuthenticator, ThreadLocalUserSession threadLocalSession, AuthenticationEvent authenticationEvent) {
- this.dbClient = dbClient;
+ public UserSessionInitializer(Settings settings, JwtHttpHandler jwtHttpHandler, BasicAuthenticator basicAuthenticator,
+ SsoAuthenticator ssoAuthenticator, ThreadLocalUserSession threadLocalSession, AuthenticationEvent authenticationEvent,
+ UserSessionFactory userSessionFactory) {
this.settings = settings;
this.jwtHttpHandler = jwtHttpHandler;
this.basicAuthenticator = basicAuthenticator;
this.ssoAuthenticator = ssoAuthenticator;
this.threadLocalSession = threadLocalSession;
this.authenticationEvent = authenticationEvent;
+ this.userSessionFactory = userSessionFactory;
}
public boolean initUserSession(HttpServletRequest request, HttpServletResponse response) {
private void setUserSession(HttpServletRequest request, HttpServletResponse response) {
Optional<UserDto> user = authenticate(request, response);
if (user.isPresent()) {
- ServerUserSession session = createForUser(dbClient, user.get());
+ UserSession session = userSessionFactory.create(user.get());
threadLocalSession.set(session);
request.setAttribute(ACCESS_LOG_LOGIN, session.getLogin());
} else {
.setMessage("User must be authenticated")
.build();
}
- threadLocalSession.set(createForAnonymous(dbClient));
+ threadLocalSession.set(userSessionFactory.createAnonymous());
request.setAttribute(ACCESS_LOG_LOGIN, "-");
}
}
import javax.servlet.http.HttpServletResponse;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.web.ServletFilter;
-import org.sonar.db.DbClient;
import org.sonar.db.user.UserDto;
import org.sonar.server.authentication.CredentialsAuthenticator;
import org.sonar.server.authentication.JwtHttpHandler;
import org.sonar.server.authentication.event.AuthenticationEvent;
import org.sonar.server.authentication.event.AuthenticationException;
import org.sonar.server.exceptions.UnauthorizedException;
-import org.sonar.server.user.ServerUserSession;
import org.sonar.server.user.ThreadLocalUserSession;
+import org.sonar.server.user.UserSessionFactory;
import org.sonar.server.ws.ServletFilterHandler;
import static java.net.HttpURLConnection.HTTP_BAD_REQUEST;
private static final String LOGIN_ACTION = "login";
public static final String LOGIN_URL = "/" + AUTHENTICATION_CONTROLLER + "/" + LOGIN_ACTION;
- private final DbClient dbClient;
private final CredentialsAuthenticator credentialsAuthenticator;
private final JwtHttpHandler jwtHttpHandler;
private final ThreadLocalUserSession threadLocalUserSession;
private final AuthenticationEvent authenticationEvent;
+ private final UserSessionFactory userSessionFactory;
- public LoginAction(DbClient dbClient, CredentialsAuthenticator credentialsAuthenticator, JwtHttpHandler jwtHttpHandler,
- ThreadLocalUserSession threadLocalUserSession, AuthenticationEvent authenticationEvent) {
- this.dbClient = dbClient;
+ public LoginAction(CredentialsAuthenticator credentialsAuthenticator, JwtHttpHandler jwtHttpHandler,
+ ThreadLocalUserSession threadLocalUserSession, AuthenticationEvent authenticationEvent, UserSessionFactory userSessionFactory) {
this.credentialsAuthenticator = credentialsAuthenticator;
this.jwtHttpHandler = jwtHttpHandler;
this.threadLocalUserSession = threadLocalUserSession;
this.authenticationEvent = authenticationEvent;
+ this.userSessionFactory = userSessionFactory;
}
@Override
try {
UserDto userDto = authenticate(request, login, password);
jwtHttpHandler.generateToken(userDto, request, response);
- threadLocalUserSession.set(ServerUserSession.createForUser(dbClient, userDto));
+ threadLocalUserSession.set(userSessionFactory.create(userDto));
} catch (AuthenticationException e) {
authenticationEvent.loginFailure(request, e);
response.setStatus(HTTP_UNAUTHORIZED);
import org.sonar.server.user.DeprecatedUserFinder;
import org.sonar.server.user.NewUserNotifier;
import org.sonar.server.user.SecurityRealmFactory;
+import org.sonar.server.user.UserSessionFactoryImpl;
import org.sonar.server.user.UserUpdater;
import org.sonar.server.user.index.UserIndex;
import org.sonar.server.user.index.UserIndexDefinition;
AuthenticationModule.class,
// users
+ UserSessionFactoryImpl.class,
SecurityRealmFactory.class,
DeprecatedUserFinder.class,
NewUserNotifier.class,
public static ForbiddenException insufficientPrivilegesException() {
return INSUFFICIENT_PRIVILEGES_EXCEPTION;
}
+
+ @Override
+ public final UserSession checkIsSystemAdministrator() {
+ if (!isSystemAdministrator()) {
+ throw insufficientPrivilegesException();
+ }
+ return this;
+ }
}
protected boolean hasProjectUuidPermission(String permission, String projectUuid) {
return true;
}
+
+ @Override
+ public boolean isSystemAdministrator() {
+ return true;
+ }
}
private void start() {
import java.util.Set;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
+import org.sonar.core.permission.GlobalPermissions;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.component.ComponentDto;
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;
-import static java.util.Objects.requireNonNull;
/**
* Implementation of {@link UserSession} used in web server
@CheckForNull
private final UserDto userDto;
private final DbClient dbClient;
- private final Supplier<List<GroupDto>> groups;
+ private final OrganizationFlags organizationFlags;
+ private final DefaultOrganizationProvider defaultOrganizationProvider;
+ private final Supplier<List<GroupDto>> groups = Suppliers.memoize(this::loadGroups);
+ private final Supplier<Boolean> isSystemAdministratorSupplier = Suppliers.memoize(this::loadIsSystemAdministrator);
private SetMultimap<String, String> projectUuidByPermission = HashMultimap.create();
private SetMultimap<String, String> permissionsByOrganizationUuid;
private Map<String, String> projectUuidByComponentUuid = newHashMap();
private List<String> projectPermissionsCheckedByUuid = new ArrayList<>();
- private ServerUserSession(DbClient dbClient, @Nullable UserDto userDto) {
- this.userDto = userDto;
+ ServerUserSession(DbClient dbClient, OrganizationFlags organizationFlags,
+ DefaultOrganizationProvider defaultOrganizationProvider, @Nullable UserDto userDto) {
this.dbClient = dbClient;
- this.groups = Suppliers.memoize(this::loadGroups);
- }
-
- public static ServerUserSession createForUser(DbClient dbClient, UserDto userDto) {
- requireNonNull(userDto, "UserDto must not be null");
- return new ServerUserSession(dbClient, userDto);
- }
-
- public static ServerUserSession createForAnonymous(DbClient dbClient) {
- return new ServerUserSession(dbClient, null);
+ this.organizationFlags = organizationFlags;
+ this.defaultOrganizationProvider = defaultOrganizationProvider;
+ this.userDto = userDto;
}
private List<GroupDto> loadGroups() {
projectPermissionsCheckedByUuid.add(permission);
}
+ @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 hasOrganizationPermission(uuidOfDefaultOrg, GlobalPermissions.SYSTEM_ADMIN);
+ }
+ // organization feature is enabled -> requires to be root
+ return false;
+ }
+ }
}
return this;
}
+ @Override
+ public boolean isSystemAdministrator() {
+ return get().isSystemAdministrator();
+ }
+
+ @Override
+ public UserSession checkIsSystemAdministrator() {
+ get().checkIsSystemAdministrator();
+ return this;
+ }
+
@Override
public boolean hasComponentPermission(String permission, ComponentDto component) {
return get().hasComponentPermission(permission, component);
* otherwise throws a {@link org.sonar.server.exceptions.ForbiddenException}.
*/
UserSession checkComponentUuidPermission(String permission, String componentUuid);
+
+ /**
+ * Whether user can administrate system, for example to use cross-organizations services
+ * like update center, system info or management of users.
+ *
+ * Returns {@code true} if:
+ * <ul>
+ * <li>{@link #isRoot()} is {@code true}</li>
+ * <li>organization feature is disabled and user is administrator of the (single) default organization</li>
+ * </ul>
+ */
+ boolean isSystemAdministrator();
+
+ /**
+ * Ensures that {@link #isSystemAdministrator()} is {@code true},
+ * otherwise throws {@link org.sonar.server.exceptions.ForbiddenException}.
+ */
+ UserSession checkIsSystemAdministrator();
+
}
--- /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.server.user;
+
+import org.sonar.api.server.ServerSide;
+import org.sonar.db.user.UserDto;
+
+@ServerSide
+public interface UserSessionFactory {
+
+ UserSession create(UserDto user);
+
+ UserSession createAnonymous();
+
+}
--- /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.server.user;
+
+import org.sonar.api.server.ServerSide;
+import org.sonar.db.DbClient;
+import org.sonar.db.user.UserDto;
+import org.sonar.server.organization.DefaultOrganizationProvider;
+import org.sonar.server.organization.OrganizationFlags;
+
+import static java.util.Objects.requireNonNull;
+
+@ServerSide
+public class UserSessionFactoryImpl implements UserSessionFactory {
+
+ private final DbClient dbClient;
+ private final DefaultOrganizationProvider defaultOrganizationProvider;
+ private final OrganizationFlags organizationFlags;
+
+ public UserSessionFactoryImpl(DbClient dbClient, DefaultOrganizationProvider defaultOrganizationProvider,
+ OrganizationFlags organizationFlags) {
+ this.dbClient = dbClient;
+ this.defaultOrganizationProvider = defaultOrganizationProvider;
+ this.organizationFlags = organizationFlags;
+ }
+
+ @Override
+ public ServerUserSession create(UserDto user) {
+ requireNonNull(user, "UserDto must not be null");
+ return new ServerUserSession(dbClient, organizationFlags, defaultOrganizationProvider, user);
+ }
+
+ @Override
+ public ServerUserSession createAnonymous() {
+ return new ServerUserSession(dbClient, organizationFlags, defaultOrganizationProvider, null);
+ }
+}
import org.sonar.db.DbTester;
import org.sonar.db.user.UserDto;
import org.sonar.server.authentication.event.AuthenticationEvent;
+import org.sonar.server.user.TestUserSessionFactory;
import org.sonar.server.user.ThreadLocalUserSession;
import org.sonar.server.user.UserSession;
private HttpServletResponse response = mock(HttpServletResponse.class);
private BaseIdentityProvider identityProvider = mock(BaseIdentityProvider.class);
private JwtHttpHandler jwtHttpHandler = mock(JwtHttpHandler.class);
+ private TestUserSessionFactory userSessionFactory = TestUserSessionFactory.standalone();
- private BaseContextFactory underTest = new BaseContextFactory(dbClient, userIdentityAuthenticator, server, jwtHttpHandler, threadLocalUserSession);
+ private BaseContextFactory underTest = new BaseContextFactory(userIdentityAuthenticator, server, jwtHttpHandler, threadLocalUserSession, userSessionFactory);
@Before
public void setUp() throws Exception {
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
import org.sonar.db.user.UserDto;
+import org.sonar.server.user.TestUserSessionFactory;
import org.sonar.server.user.ThreadLocalUserSession;
import org.sonar.server.user.UserSession;
private Server server = mock(Server.class);
private OAuthCsrfVerifier csrfVerifier = mock(OAuthCsrfVerifier.class);
private JwtHttpHandler jwtHttpHandler = mock(JwtHttpHandler.class);
+ private TestUserSessionFactory userSessionFactory = TestUserSessionFactory.standalone();
private HttpServletRequest request = mock(HttpServletRequest.class);
private HttpServletResponse response = mock(HttpServletResponse.class);
private HttpSession session = mock(HttpSession.class);
private OAuth2IdentityProvider identityProvider = mock(OAuth2IdentityProvider.class);
- private OAuth2ContextFactory underTest = new OAuth2ContextFactory(dbClient, threadLocalUserSession, userIdentityAuthenticator, server, csrfVerifier, jwtHttpHandler);
+ private OAuth2ContextFactory underTest = new OAuth2ContextFactory(threadLocalUserSession, userIdentityAuthenticator, server, csrfVerifier, jwtHttpHandler, userSessionFactory);
@Before
public void setUp() throws Exception {
import org.sonar.server.authentication.event.AuthenticationEvent;
import org.sonar.server.authentication.event.AuthenticationException;
import org.sonar.server.user.ServerUserSession;
+import org.sonar.server.user.TestUserSessionFactory;
import org.sonar.server.user.ThreadLocalUserSession;
import org.sonar.server.user.UserSession;
private BasicAuthenticator basicAuthenticator = mock(BasicAuthenticator.class);
private SsoAuthenticator ssoAuthenticator = mock(SsoAuthenticator.class);
private AuthenticationEvent authenticationEvent = mock(AuthenticationEvent.class);
-
+ private TestUserSessionFactory userSessionFactory = TestUserSessionFactory.standalone();
private Settings settings = new MapSettings();
private UserDto user = newUserDto();
- private UserSessionInitializer underTest = new UserSessionInitializer(dbClient, settings, jwtHttpHandler, basicAuthenticator,
- ssoAuthenticator, userSession, authenticationEvent);
+ private UserSessionInitializer underTest = new UserSessionInitializer(settings, jwtHttpHandler, basicAuthenticator,
+ ssoAuthenticator, userSession, authenticationEvent, userSessionFactory);
@Before
public void setUp() throws Exception {
import org.sonar.server.authentication.event.AuthenticationEvent;
import org.sonar.server.authentication.event.AuthenticationException;
import org.sonar.server.exceptions.UnauthorizedException;
+import org.sonar.server.user.TestUserSessionFactory;
import org.sonar.server.user.ThreadLocalUserSession;
import static org.assertj.core.api.Assertions.assertThat;
private CredentialsAuthenticator credentialsAuthenticator = mock(CredentialsAuthenticator.class);
private JwtHttpHandler jwtHttpHandler = mock(JwtHttpHandler.class);
private AuthenticationEvent authenticationEvent = mock(AuthenticationEvent.class);
+ private TestUserSessionFactory userSessionFactory = TestUserSessionFactory.standalone();
private UserDto user = UserTesting.newUserDto().setLogin(LOGIN);
-
- private LoginAction underTest = new LoginAction(dbClient, credentialsAuthenticator, jwtHttpHandler, threadLocalUserSession, authenticationEvent);
+ private LoginAction underTest = new LoginAction(credentialsAuthenticator, jwtHttpHandler, threadLocalUserSession, authenticationEvent, userSessionFactory);
@Before
public void setUp() throws Exception {
private HashMultimap<String, String> permissionsByOrganizationUuid = HashMultimap.create();
private Map<String, String> projectUuidByComponentUuid = newHashMap();
private List<String> projectPermissionsCheckedByUuid = newArrayList();
+ private boolean systemAdministrator = false;
protected AbstractMockUserSession(Class<T> clazz) {
this.clazz = clazz;
permissionsByOrganizationUuid.put(organizationUuid, permission);
return clazz.cast(this);
}
+
+ public T setSystemAdministrator(boolean b) {
+ this.systemAdministrator = b;
+ return clazz.cast(this);
+ }
+
+ @Override
+ public boolean isSystemAdministrator() {
+ return systemAdministrator;
+ }
}
return this;
}
+ @Override
+ public boolean isSystemAdministrator() {
+ return currentUserSession.isSystemAdministrator();
+ }
+
+ @Override
+ public UserSession checkIsSystemAdministrator() {
+ currentUserSession.checkIsSystemAdministrator();
+ return this;
+ }
+
@Override
public UserSession checkOrganizationPermission(String organizationUuid, String permission) {
currentUserSession.checkOrganizationPermission(organizationUuid, permission);
// verify the session used inside Privileged task
assertThat(catcher.userSession.isLoggedIn()).isFalse();
assertThat(catcher.userSession.hasComponentPermission("any permission", new ComponentDto())).isTrue();
+ assertThat(catcher.userSession.isSystemAdministrator()).isTrue();
// verify session in place after task is done
assertThat(threadLocalUserSession.get()).isSameAs(session);
import org.sonar.db.user.GroupDto;
import org.sonar.db.user.UserDto;
import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.organization.TestDefaultOrganizationProvider;
+import org.sonar.server.organization.TestOrganizationFlags;
import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.core.permission.GlobalPermissions.PROVISIONING;
import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN;
import static org.sonar.db.user.UserTesting.newUserDto;
-import static org.sonar.server.user.ServerUserSession.createForAnonymous;
-import static org.sonar.server.user.ServerUserSession.createForUser;
public class ServerUserSessionTest {
private static final String LOGIN = "marius";
private DbClient dbClient = db.getDbClient();
private UserDto userDto = newUserDto().setLogin(LOGIN);
+ private TestOrganizationFlags organizationFlags = TestOrganizationFlags.standalone();
+ private TestDefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db);
private OrganizationDto organization;
private ComponentDto project;
session.checkComponentUuidPermission(UserRole.USER, "another-uuid");
}
- @Test
- public void fail_if_user_dto_is_null() throws Exception {
- expectedException.expect(NullPointerException.class);
- newUserSession(null);
- }
-
@Test
public void anonymous_user() throws Exception {
UserSession session = newAnonymousSession();
}
@Test
- public void hasOrganizationPermission_for_logged_in_user() {
+ public void test_hasOrganizationPermission_for_logged_in_user() {
OrganizationDto org = db.organizations().insert();
ComponentDto project = db.components().insertProject(org);
db.users().insertPermissionOnUser(org, userDto, PROVISIONING);
assertThat(session.hasOrganizationPermission("another-org", PROVISIONING)).isFalse();
}
- private ServerUserSession newUserSession(UserDto userDto) {
- return createForUser(dbClient, userDto);
+ @Test
+ public void isSystemAdministrator_returns_true_if_org_feature_is_enabled_and_user_is_root() {
+ organizationFlags.setEnabled(true);
+ userDto = db.users().makeRoot(userDto);
+ UserSession session = newUserSession(userDto);
+
+ assertThat(session.isSystemAdministrator()).isTrue();
+ }
+
+ @Test
+ public void isSystemAdministrator_returns_false_if_org_feature_is_enabled_and_user_is_not_root() {
+ organizationFlags.setEnabled(true);
+ userDto = db.users().makeNotRoot(userDto);
+ UserSession session = newUserSession(userDto);
+
+ assertThat(session.isSystemAdministrator()).isFalse();
+ }
+
+ @Test
+ public void isSystemAdministrator_returns_false_if_org_feature_is_enabled_and_user_is_administrator_of_default_organization() {
+ organizationFlags.setEnabled(true);
+ userDto = db.users().makeNotRoot(userDto);
+ db.users().insertPermissionOnUser(db.getDefaultOrganization(), userDto, SYSTEM_ADMIN);
+ UserSession session = newUserSession(userDto);
+
+ assertThat(session.isSystemAdministrator()).isFalse();
+ }
+
+ @Test
+ public void isSystemAdministrator_returns_true_if_org_feature_is_disabled_and_user_is_administrator_of_default_organization() {
+ organizationFlags.setEnabled(false);
+ userDto = db.users().makeNotRoot(userDto);
+ db.users().insertPermissionOnUser(db.getDefaultOrganization(), userDto, SYSTEM_ADMIN);
+ UserSession session = newUserSession(userDto);
+
+ assertThat(session.isSystemAdministrator()).isTrue();
+ }
+
+ @Test
+ public void isSystemAdministrator_returns_false_if_org_feature_is_disabled_and_user_is_not_administrator_of_default_organization() {
+ organizationFlags.setEnabled(true);
+ userDto = db.users().makeNotRoot(userDto);
+ db.users().insertPermissionOnUser(db.getDefaultOrganization(), userDto, PROVISIONING);
+ UserSession session = newUserSession(userDto);
+
+ assertThat(session.isSystemAdministrator()).isFalse();
+ }
+
+ @Test
+ public void keep_isSystemAdministrator_flag_in_cache() {
+ organizationFlags.setEnabled(false);
+ userDto = db.users().makeNotRoot(userDto);
+ db.users().insertPermissionOnUser(db.getDefaultOrganization(), userDto, SYSTEM_ADMIN);
+ UserSession session = newUserSession(userDto);
+
+ session.checkIsSystemAdministrator();
+
+ db.getDbClient().userDao().deactivateUserByLogin(db.getSession(), userDto.getLogin());
+ db.commit();
+
+ // should fail but succeeds because flag is kept in cache
+ session.checkIsSystemAdministrator();
+ }
+
+ @Test
+ public void checkIsSystemAdministrator_succeeds_if_system_administrator() {
+ organizationFlags.setEnabled(true);
+ userDto = db.users().makeRoot(userDto);
+ UserSession session = newUserSession(userDto);
+
+ session.checkIsSystemAdministrator();
+ }
+
+ @Test
+ public void checkIsSystemAdministrator_throws_ForbiddenException_if_not_system_administrator() {
+ organizationFlags.setEnabled(true);
+ userDto = db.users().makeNotRoot(userDto);
+ UserSession session = newUserSession(userDto);
+
+ expectedException.expect(ForbiddenException.class);
+ expectedException.expectMessage("Insufficient privileges");
+
+ session.checkIsSystemAdministrator();
+ }
+
+ private ServerUserSession newUserSession(@Nullable UserDto userDto) {
+ return new ServerUserSession(dbClient, organizationFlags, defaultOrganizationProvider, userDto);
}
private ServerUserSession newAnonymousSession() {
- return createForAnonymous(dbClient);
+ return newUserSession(null);
}
private void addProjectPermissions(ComponentDto component, String... permissions) {
--- /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.server.user;
+
+import java.util.Collection;
+import java.util.Optional;
+import javax.annotation.Nullable;
+import org.sonar.db.user.GroupDto;
+import org.sonar.db.user.UserDto;
+
+import static java.util.Objects.requireNonNull;
+
+/**
+ * Simple implementation of {@link UserSessionFactory}. It creates
+ * instances of {@link UserSession} that don't manage groups nor
+ * permissions. Only basic user information like {@link UserSession#isLoggedIn()}
+ * and {@link UserSession#getLogin()} are available. The methods
+ * relying on groups or permissions throw {@link UnsupportedOperationException}.
+ */
+public class TestUserSessionFactory implements UserSessionFactory {
+
+ private TestUserSessionFactory() {
+ }
+
+ @Override
+ public UserSession create(UserDto user) {
+ return new TestUserSession(requireNonNull(user));
+ }
+
+ @Override
+ public UserSession createAnonymous() {
+ return new TestUserSession(null);
+ }
+
+ public static TestUserSessionFactory standalone() {
+ return new TestUserSessionFactory();
+ }
+
+ private static class TestUserSession extends AbstractUserSession {
+ private final UserDto user;
+
+ public TestUserSession(@Nullable UserDto user) {
+ this.user = user;
+ }
+
+ @Override
+ public String getLogin() {
+ return user != null ? user.getLogin() : null;
+ }
+
+ @Override
+ public String getName() {
+ return user != null ? user.getName() : null;
+ }
+
+ @Override
+ public Integer getUserId() {
+ return user != null ? user.getId().intValue() : null;
+ }
+
+ @Override
+ public Collection<GroupDto> getGroups() {
+ throw notImplemented();
+ }
+
+ @Override
+ public boolean isLoggedIn() {
+ return user != null;
+ }
+
+ @Override
+ public boolean isRoot() {
+ throw notImplemented();
+ }
+
+ @Override
+ protected boolean hasOrganizationPermissionImpl(String organizationUuid, String permission) {
+ throw notImplemented();
+ }
+
+ @Override
+ protected Optional<String> componentUuidToProjectUuid(String componentUuid) {
+ throw notImplemented();
+ }
+
+ @Override
+ protected boolean hasProjectUuidPermission(String permission, String projectUuid) {
+ throw notImplemented();
+ }
+
+ @Override
+ public boolean isSystemAdministrator() {
+ throw notImplemented();
+ }
+
+ private static RuntimeException notImplemented() {
+ return new UnsupportedOperationException("not implemented");
+ }
+ }
+}