mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-13 00:45:44 +01:00
create _anonymous user when anonymous access activated and user does not exist yet / also create _anonymous user on system start if required
This commit is contained in:
@@ -6,6 +6,8 @@ import com.webcohesion.enunciate.metadata.rs.TypeHint;
|
||||
import sonia.scm.config.ConfigurationPermissions;
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
import sonia.scm.repository.NamespaceStrategyValidator;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.user.UserManager;
|
||||
import sonia.scm.util.ScmConfigurationUtil;
|
||||
import sonia.scm.web.VndMediaType;
|
||||
|
||||
@@ -29,15 +31,17 @@ public class ConfigResource {
|
||||
private final ScmConfigurationToConfigDtoMapper configToDtoMapper;
|
||||
private final ScmConfiguration configuration;
|
||||
private final NamespaceStrategyValidator namespaceStrategyValidator;
|
||||
private final UserManager userManager;
|
||||
|
||||
@Inject
|
||||
public ConfigResource(ConfigDtoToScmConfigurationMapper dtoToConfigMapper,
|
||||
ScmConfigurationToConfigDtoMapper configToDtoMapper,
|
||||
ScmConfiguration configuration, NamespaceStrategyValidator namespaceStrategyValidator) {
|
||||
ScmConfiguration configuration, NamespaceStrategyValidator namespaceStrategyValidator, UserManager userManager) {
|
||||
this.dtoToConfigMapper = dtoToConfigMapper;
|
||||
this.configToDtoMapper = configToDtoMapper;
|
||||
this.configuration = configuration;
|
||||
this.namespaceStrategyValidator = namespaceStrategyValidator;
|
||||
this.userManager = userManager;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,6 +96,10 @@ public class ConfigResource {
|
||||
ScmConfigurationUtil.getInstance().store(configuration);
|
||||
}
|
||||
|
||||
if (config.isAnonymousAccessEnabled() && !userManager.contains("_anonymous")) {
|
||||
userManager.create(new User("_anonymous"));
|
||||
}
|
||||
|
||||
return Response.noContent().build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.google.common.annotations.VisibleForTesting;
|
||||
import org.apache.shiro.authc.credential.PasswordService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
import sonia.scm.plugin.Extension;
|
||||
import sonia.scm.security.PermissionAssigner;
|
||||
import sonia.scm.security.PermissionDescriptor;
|
||||
@@ -47,12 +48,14 @@ public class SetupContextListener implements ServletContextListener {
|
||||
private final UserManager userManager;
|
||||
private final PasswordService passwordService;
|
||||
private final PermissionAssigner permissionAssigner;
|
||||
private final ScmConfiguration scmConfiguration;
|
||||
|
||||
@Inject
|
||||
public SetupAction(UserManager userManager, PasswordService passwordService, PermissionAssigner permissionAssigner) {
|
||||
public SetupAction(UserManager userManager, PasswordService passwordService, PermissionAssigner permissionAssigner, ScmConfiguration scmConfiguration) {
|
||||
this.userManager = userManager;
|
||||
this.passwordService = passwordService;
|
||||
this.permissionAssigner = permissionAssigner;
|
||||
this.scmConfiguration = scmConfiguration;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -60,6 +63,13 @@ public class SetupContextListener implements ServletContextListener {
|
||||
if (isFirstStart()) {
|
||||
createAdminAccount();
|
||||
}
|
||||
if (anonymousUserRequiredButNotExists()) {
|
||||
userManager.create(new User("_anonymous"));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean anonymousUserRequiredButNotExists() {
|
||||
return scmConfiguration.isAnonymousAccessEnabled() && !userManager.contains("_anonymous");
|
||||
}
|
||||
|
||||
private boolean isFirstStart() {
|
||||
|
||||
@@ -16,6 +16,8 @@ import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
import sonia.scm.repository.NamespaceStrategyValidator;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.user.UserManager;
|
||||
import sonia.scm.web.VndMediaType;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
@@ -29,7 +31,9 @@ import java.nio.charset.StandardCharsets;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.mockito.MockitoAnnotations.initMocks;
|
||||
|
||||
@SubjectAware(
|
||||
@@ -50,6 +54,9 @@ public class ConfigResourceTest {
|
||||
@SuppressWarnings("unused") // Is injected
|
||||
private ResourceLinks resourceLinks = ResourceLinksMock.createMock(baseUri);
|
||||
|
||||
@Mock
|
||||
private UserManager userManager;
|
||||
|
||||
@Mock
|
||||
private NamespaceStrategyValidator namespaceStrategyValidator;
|
||||
|
||||
@@ -69,7 +76,7 @@ public class ConfigResourceTest {
|
||||
public void prepareEnvironment() {
|
||||
initMocks(this);
|
||||
|
||||
ConfigResource configResource = new ConfigResource(dtoToConfigMapper, configToDtoMapper, createConfiguration(), namespaceStrategyValidator);
|
||||
ConfigResource configResource = new ConfigResource(dtoToConfigMapper, configToDtoMapper, createConfiguration(), namespaceStrategyValidator, userManager);
|
||||
|
||||
dispatcher.getRegistry().addSingletonResource(configResource);
|
||||
}
|
||||
@@ -114,6 +121,45 @@ public class ConfigResourceTest {
|
||||
assertTrue("link not found", response.getContentAsString().contains("\"update\":{\"href\":\"/v2/config"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SubjectAware(username = "readWrite")
|
||||
public void shouldUpdateConfigAndCreateAnonymousUser() throws URISyntaxException, IOException {
|
||||
MockHttpRequest request = post("sonia/scm/api/v2/config-test-update-with-anonymous-access.json");
|
||||
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
dispatcher.invoke(request, response);
|
||||
assertEquals(HttpServletResponse.SC_NO_CONTENT, response.getStatus());
|
||||
|
||||
request = MockHttpRequest.get("/" + ConfigResource.CONFIG_PATH_V2);
|
||||
response = new MockHttpResponse();
|
||||
dispatcher.invoke(request, response);
|
||||
assertEquals(HttpServletResponse.SC_OK, response.getStatus());
|
||||
assertTrue(response.getContentAsString().contains("\"proxyPassword\":\"newPassword\""));
|
||||
assertTrue(response.getContentAsString().contains("\"self\":{\"href\":\"/v2/config"));
|
||||
assertTrue("link not found", response.getContentAsString().contains("\"update\":{\"href\":\"/v2/config"));
|
||||
verify(userManager).create(new User("_anonymous"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SubjectAware(username = "readWrite")
|
||||
public void shouldUpdateConfigAndNotCreateAnonymousUserIfAlreadyExists() throws URISyntaxException, IOException {
|
||||
when(userManager.contains("_anonymous")).thenReturn(true);
|
||||
MockHttpRequest request = post("sonia/scm/api/v2/config-test-update-with-anonymous-access.json");
|
||||
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
dispatcher.invoke(request, response);
|
||||
assertEquals(HttpServletResponse.SC_NO_CONTENT, response.getStatus());
|
||||
|
||||
request = MockHttpRequest.get("/" + ConfigResource.CONFIG_PATH_V2);
|
||||
response = new MockHttpResponse();
|
||||
dispatcher.invoke(request, response);
|
||||
assertEquals(HttpServletResponse.SC_OK, response.getStatus());
|
||||
assertTrue(response.getContentAsString().contains("\"proxyPassword\":\"newPassword\""));
|
||||
assertTrue(response.getContentAsString().contains("\"self\":{\"href\":\"/v2/config"));
|
||||
assertTrue("link not found", response.getContentAsString().contains("\"update\":{\"href\":\"/v2/config"));
|
||||
verify(userManager, never()).create(new User("_anonymous"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SubjectAware(username = "readOnly")
|
||||
public void shouldNotUpdateConfigWhenNotAuthorized() throws URISyntaxException, IOException {
|
||||
@@ -152,6 +198,7 @@ public class ConfigResourceTest {
|
||||
private static ScmConfiguration createConfiguration() {
|
||||
ScmConfiguration scmConfiguration = new ScmConfiguration();
|
||||
scmConfiguration.setProxyPassword("heartOfGold");
|
||||
scmConfiguration.setAnonymousAccessEnabled(true);
|
||||
|
||||
return scmConfiguration;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.mockito.junit.jupiter.MockitoSettings;
|
||||
import org.mockito.quality.Strictness;
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
import sonia.scm.security.PermissionAssigner;
|
||||
import sonia.scm.security.PermissionDescriptor;
|
||||
import sonia.scm.user.User;
|
||||
@@ -23,7 +24,12 @@ import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.mockito.Mockito.anyString;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class SetupContextListenerTest {
|
||||
@@ -40,12 +46,20 @@ class SetupContextListenerTest {
|
||||
@Mock
|
||||
private PasswordService passwordService;
|
||||
|
||||
@Mock
|
||||
ScmConfiguration scmConfiguration;
|
||||
|
||||
@Mock
|
||||
private PermissionAssigner permissionAssigner;
|
||||
|
||||
@InjectMocks
|
||||
private SetupContextListener.SetupAction setupAction;
|
||||
|
||||
@BeforeEach
|
||||
void mockScmConfiguration() {
|
||||
when(scmConfiguration.isAnonymousAccessEnabled()).thenReturn(false);
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void setupObjectUnderTest() {
|
||||
doAnswer(ic -> {
|
||||
@@ -90,6 +104,38 @@ class SetupContextListenerTest {
|
||||
verify(permissionAssigner, never()).setPermissionsForUser(anyString(), any(Collection.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldCreateAnonymousUserIfRequired() {
|
||||
List<User> users = Lists.newArrayList(UserTestData.createTrillian());
|
||||
when(userManager.getAll()).thenReturn(users);
|
||||
when(scmConfiguration.isAnonymousAccessEnabled()).thenReturn(true);
|
||||
|
||||
setupContextListener.contextInitialized(null);
|
||||
|
||||
verify(userManager).create(new User("_anonymous"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotCreateAnonymousUserIfNotRequired() {
|
||||
List<User> users = Lists.newArrayList(UserTestData.createTrillian());
|
||||
when(userManager.getAll()).thenReturn(users);
|
||||
|
||||
setupContextListener.contextInitialized(null);
|
||||
|
||||
verify(userManager, never()).create(new User("_anonymous"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotCreateAnonymousUserIfAlreadyExists() {
|
||||
List<User> users = Lists.newArrayList(new User("_anonymous"));
|
||||
when(userManager.getAll()).thenReturn(users);
|
||||
when(scmConfiguration.isAnonymousAccessEnabled()).thenReturn(true);
|
||||
|
||||
setupContextListener.contextInitialized(null);
|
||||
|
||||
verify(userManager, times(1)).create(new User("_anonymous"));
|
||||
}
|
||||
|
||||
private void verifyAdminPermissionsAssigned() {
|
||||
ArgumentCaptor<String> usernameCaptor = ArgumentCaptor.forClass(String.class);
|
||||
ArgumentCaptor<Collection<PermissionDescriptor>> permissionCaptor = ArgumentCaptor.forClass(Collection.class);
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"proxyPassword": "newPassword",
|
||||
"anonymousAccessEnabled": "true"
|
||||
}
|
||||
Reference in New Issue
Block a user