mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-14 09:25:43 +01:00
merge with branch 2.0.0-m3
This commit is contained in:
@@ -0,0 +1,263 @@
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.github.sdorra.shiro.ShiroRule;
|
||||
import com.github.sdorra.shiro.SubjectAware;
|
||||
import org.apache.shiro.util.ThreadContext;
|
||||
import org.assertj.core.util.Lists;
|
||||
import org.jboss.resteasy.core.Dispatcher;
|
||||
import org.jboss.resteasy.mock.MockHttpRequest;
|
||||
import org.jboss.resteasy.mock.MockHttpResponse;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import sonia.scm.Manager;
|
||||
import sonia.scm.group.DefaultGroupManager;
|
||||
import sonia.scm.group.Group;
|
||||
import sonia.scm.group.GroupManager;
|
||||
import sonia.scm.group.xml.XmlGroupDAO;
|
||||
import sonia.scm.store.ConfigurationStore;
|
||||
import sonia.scm.store.ConfigurationStoreFactory;
|
||||
import sonia.scm.user.DefaultUserManager;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.user.UserManager;
|
||||
import sonia.scm.user.xml.XmlUserDAO;
|
||||
import sonia.scm.web.VndMediaType;
|
||||
import sonia.scm.xml.XmlDatabase;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.mockito.MockitoAnnotations.initMocks;
|
||||
import static sonia.scm.api.v2.resources.DispatcherMock.createDispatcher;
|
||||
|
||||
@SubjectAware(configuration = "classpath:sonia/scm/shiro-002.ini")
|
||||
@RunWith(MockitoJUnitRunner.Silent.class)
|
||||
public class AutoCompleteResourceTest {
|
||||
|
||||
@Rule
|
||||
public final ShiroRule shiroRule = new ShiroRule();
|
||||
|
||||
public static final String URL = "/" + AutoCompleteResource.PATH;
|
||||
private final Integer defaultLimit = Manager.DEFAULT_LIMIT;
|
||||
private Dispatcher dispatcher;
|
||||
|
||||
private XmlUserDAO userDao;
|
||||
private XmlGroupDAO groupDao;
|
||||
private XmlDatabase xmlDB;
|
||||
private ObjectMapper jsonObjectMapper = new ObjectMapper();
|
||||
|
||||
@Before
|
||||
public void prepareEnvironment() {
|
||||
initMocks(this);
|
||||
ConfigurationStoreFactory storeFactory = mock(ConfigurationStoreFactory.class);
|
||||
ConfigurationStore<Object> storeConfig = mock(ConfigurationStore.class);
|
||||
xmlDB = mock(XmlDatabase.class);
|
||||
when(storeConfig.get()).thenReturn(xmlDB);
|
||||
when(storeFactory.getStore(any(), any())).thenReturn(storeConfig);
|
||||
XmlUserDAO userDao = new XmlUserDAO(storeFactory);
|
||||
this.userDao = spy(userDao);
|
||||
XmlGroupDAO groupDAO = new XmlGroupDAO(storeFactory);
|
||||
groupDao = spy(groupDAO);
|
||||
ReducedObjectModelToDtoMapperImpl mapper = new ReducedObjectModelToDtoMapperImpl();
|
||||
UserManager userManager = new DefaultUserManager(this.userDao);
|
||||
GroupManager groupManager = new DefaultGroupManager(groupDao);
|
||||
AutoCompleteResource autoCompleteResource = new AutoCompleteResource(mapper, userManager, groupManager);
|
||||
dispatcher = createDispatcher(autoCompleteResource);
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanupContext() {
|
||||
ThreadContext.unbindSubject();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldGet400IfParameterLengthLessThan2CharsForUserSearch() throws Exception {
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.get("/" + AutoCompleteResource.PATH + "users?q=a")
|
||||
.contentType(VndMediaType.AUTOCOMPLETE)
|
||||
.accept(VndMediaType.AUTOCOMPLETE);
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
assertEquals(400, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SubjectAware(username = "trillian", password = "secret")
|
||||
public void shouldGet400OnFailedParameterForUserSearch() throws Exception {
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.get("/" + AutoCompleteResource.PATH + "users")
|
||||
.contentType(VndMediaType.AUTOCOMPLETE)
|
||||
.accept(VndMediaType.AUTOCOMPLETE);
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
assertEquals(400, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SubjectAware(username = "trillian", password = "secret")
|
||||
public void shouldSearchUsers() throws Exception {
|
||||
ArrayList<User> users = Lists.newArrayList(createMockUser("YuCantFindMe", "ha ha"), createMockUser("user1", "User 1"), createMockUser("user2", "User 2"));
|
||||
String searched = "user";
|
||||
when(xmlDB.values()).thenReturn(users);
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.get("/" + AutoCompleteResource.PATH + "users?q=" + searched)
|
||||
.contentType(VndMediaType.AUTOCOMPLETE)
|
||||
.accept(VndMediaType.AUTOCOMPLETE);
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
assertEquals(HttpServletResponse.SC_OK, response.getStatus());
|
||||
|
||||
assertResultSize(response, 2);
|
||||
assertTrue(response.getContentAsString().contains("\"id\":\"user1\""));
|
||||
assertTrue(response.getContentAsString().contains("\"displayName\":\"User 1\""));
|
||||
assertTrue(response.getContentAsString().contains("\"id\":\"user2\""));
|
||||
assertTrue(response.getContentAsString().contains("\"displayName\":\"User 2\""));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SubjectAware(username = "user_without_autocomplete_permission", password = "secret")
|
||||
public void shouldGet403OnAutoCompleteUsers() throws Exception {
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.get("/" + AutoCompleteResource.PATH + "users?q=user" )
|
||||
.contentType(VndMediaType.AUTOCOMPLETE)
|
||||
.accept(VndMediaType.AUTOCOMPLETE);
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
assertEquals(HttpServletResponse.SC_FORBIDDEN, response.getStatus());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@SubjectAware(username = "trillian", password = "secret")
|
||||
public void shouldSearchUsersWithDefaultLimitLength() throws Exception {
|
||||
List<User> userList = IntStream.range(0, 10).boxed().map(i -> createMockUser("user" + i, "User " + i)).collect(Collectors.toList());
|
||||
when(xmlDB.values()).thenReturn(userList);
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.get("/" + AutoCompleteResource.PATH + "users?q=user")
|
||||
.contentType(VndMediaType.AUTOCOMPLETE)
|
||||
.accept(VndMediaType.AUTOCOMPLETE);
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
assertEquals(HttpServletResponse.SC_OK, response.getStatus());
|
||||
assertResultSize(response, defaultLimit);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SubjectAware(username = "trillian", password = "secret")
|
||||
public void shouldGet400OnFailedParameterForGroupSearch() throws Exception {
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.get("/" + AutoCompleteResource.PATH + "groups")
|
||||
.contentType(VndMediaType.AUTOCOMPLETE)
|
||||
.accept(VndMediaType.AUTOCOMPLETE);
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
assertEquals(400, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SubjectAware(username = "trillian", password = "secret")
|
||||
public void shouldGet400IfParameterLengthLessThan2CharsForGroupSearch() throws Exception {
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.get("/" + AutoCompleteResource.PATH + "groups?q=a")
|
||||
.contentType(VndMediaType.AUTOCOMPLETE)
|
||||
.accept(VndMediaType.AUTOCOMPLETE);
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
assertEquals(400, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SubjectAware(username = "trillian", password = "secret")
|
||||
public void shouldSearchGroups() throws Exception {
|
||||
ArrayList<Group> groups = Lists.newArrayList(createMockGroup("YuCantFindMe"), createMockGroup("group_1"), createMockGroup("group_2"));
|
||||
String searched = "group";
|
||||
when(xmlDB.values()).thenReturn(groups);
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.get("/" + AutoCompleteResource.PATH + "groups?q=" + searched)
|
||||
.contentType(VndMediaType.AUTOCOMPLETE)
|
||||
.accept(VndMediaType.AUTOCOMPLETE);
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
assertEquals(HttpServletResponse.SC_OK, response.getStatus());
|
||||
assertResultSize(response, 2);
|
||||
assertTrue(response.getContentAsString().contains("\"id\":\"group_1\""));
|
||||
assertTrue(response.getContentAsString().contains("\"displayName\":\"group_1\""));
|
||||
assertTrue(response.getContentAsString().contains("\"id\":\"group_2\""));
|
||||
assertTrue(response.getContentAsString().contains("\"displayName\":\"group_2\""));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SubjectAware(username = "user_without_autocomplete_permission", password = "secret")
|
||||
public void shouldGet403OnAutoCompleteGroups() throws Exception {
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.get("/" + AutoCompleteResource.PATH + "groups?q=user" )
|
||||
.contentType(VndMediaType.AUTOCOMPLETE)
|
||||
.accept(VndMediaType.AUTOCOMPLETE);
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
assertEquals(HttpServletResponse.SC_FORBIDDEN, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SubjectAware(username = "trillian", password = "secret")
|
||||
public void shouldSearchGroupsWithDefaultLimitLength() throws Exception {
|
||||
List<Group> groups = IntStream.range(0, 10).boxed().map(i -> createMockGroup("group_" + i)).collect(Collectors.toList());
|
||||
when(xmlDB.values()).thenReturn(groups);
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.get("/" + AutoCompleteResource.PATH + "groups?q=group")
|
||||
.contentType(VndMediaType.AUTOCOMPLETE)
|
||||
.accept(VndMediaType.AUTOCOMPLETE);
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
assertEquals(HttpServletResponse.SC_OK, response.getStatus());
|
||||
assertResultSize(response, defaultLimit);
|
||||
}
|
||||
|
||||
private User createMockUser(String id, String name) {
|
||||
return new User(id, name, "em@l.de");
|
||||
}
|
||||
|
||||
private Group createMockGroup(String name) {
|
||||
Group group = new Group("type", name);
|
||||
group.setDescription(name);
|
||||
return group;
|
||||
}
|
||||
|
||||
private void assertResultSize(MockHttpResponse response, int size) throws java.io.IOException {
|
||||
ReducedObjectModelDto[] reducedObjectModelDtos = jsonObjectMapper.readValue(response.getContentAsString(), ReducedObjectModelDto[].class);
|
||||
assertEquals(reducedObjectModelDtos.length, size);
|
||||
}
|
||||
}
|
||||
@@ -8,34 +8,26 @@ import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import sonia.scm.repository.BrowserResult;
|
||||
import sonia.scm.repository.FileObject;
|
||||
import sonia.scm.repository.NamespaceAndName;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.mockito.MockitoAnnotations.initMocks;
|
||||
|
||||
public class BrowserResultToBrowserResultDtoMapperTest {
|
||||
public class BrowserResultToFileObjectDtoMapperTest {
|
||||
|
||||
private final URI baseUri = URI.create("http://example.com/base/");
|
||||
@SuppressWarnings("unused") // Is injected
|
||||
private final ResourceLinks resourceLinks = ResourceLinksMock.createMock(baseUri);
|
||||
|
||||
@Mock
|
||||
private FileObjectToFileObjectDtoMapper fileObjectToFileObjectDtoMapper;
|
||||
|
||||
@InjectMocks
|
||||
private BrowserResultToBrowserResultDtoMapper mapper;
|
||||
private FileObjectToFileObjectDtoMapperImpl fileObjectToFileObjectDtoMapper;
|
||||
|
||||
private BrowserResultToFileObjectDtoMapper mapper;
|
||||
|
||||
private final Subject subject = mock(Subject.class);
|
||||
private final ThreadState subjectThreadState = new SubjectThreadState(subject);
|
||||
@@ -47,6 +39,7 @@ public class BrowserResultToBrowserResultDtoMapperTest {
|
||||
@Before
|
||||
public void init() {
|
||||
initMocks(this);
|
||||
mapper = new BrowserResultToFileObjectDtoMapper(fileObjectToFileObjectDtoMapper);
|
||||
subjectThreadState.bind();
|
||||
ThreadContext.bind(subject);
|
||||
|
||||
@@ -63,9 +56,6 @@ public class BrowserResultToBrowserResultDtoMapperTest {
|
||||
fileObject2.setPath("/path/object/2");
|
||||
fileObject2.setDescription("description of file object 2");
|
||||
fileObject2.setDirectory(true);
|
||||
|
||||
when(fileObjectToFileObjectDtoMapper.map(any(FileObject.class), any(NamespaceAndName.class), anyString()))
|
||||
.thenReturn(new FileObjectDto());
|
||||
}
|
||||
|
||||
@After
|
||||
@@ -77,7 +67,7 @@ public class BrowserResultToBrowserResultDtoMapperTest {
|
||||
public void shouldMapAttributesCorrectly() {
|
||||
BrowserResult browserResult = createBrowserResult();
|
||||
|
||||
BrowserResultDto dto = mapper.map(browserResult, new NamespaceAndName("foo", "bar"), "path");
|
||||
FileObjectDto dto = mapper.map(browserResult, new NamespaceAndName("foo", "bar"));
|
||||
|
||||
assertEqualAttributes(browserResult, dto);
|
||||
}
|
||||
@@ -87,10 +77,9 @@ public class BrowserResultToBrowserResultDtoMapperTest {
|
||||
BrowserResult browserResult = createBrowserResult();
|
||||
NamespaceAndName namespaceAndName = new NamespaceAndName("foo", "bar");
|
||||
|
||||
BrowserResultDto dto = mapper.map(browserResult, namespaceAndName, "path");
|
||||
FileObjectDto dto = mapper.map(browserResult, namespaceAndName);
|
||||
|
||||
verify(fileObjectToFileObjectDtoMapper).map(fileObject1, namespaceAndName, "Revision");
|
||||
verify(fileObjectToFileObjectDtoMapper).map(fileObject2, namespaceAndName, "Revision");
|
||||
assertThat(dto.getEmbedded().getItemsBy("children")).hasSize(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -98,28 +87,27 @@ public class BrowserResultToBrowserResultDtoMapperTest {
|
||||
BrowserResult browserResult = createBrowserResult();
|
||||
NamespaceAndName namespaceAndName = new NamespaceAndName("foo", "bar");
|
||||
|
||||
BrowserResultDto dto = mapper.map(browserResult, namespaceAndName, "path");
|
||||
FileObjectDto dto = mapper.map(browserResult, namespaceAndName);
|
||||
|
||||
assertThat(dto.getLinks().getLinkBy("self").get().getHref()).contains("path");
|
||||
}
|
||||
|
||||
private BrowserResult createBrowserResult() {
|
||||
BrowserResult browserResult = new BrowserResult();
|
||||
browserResult.setRevision("Revision");
|
||||
browserResult.setFiles(createFileObjects());
|
||||
|
||||
return browserResult;
|
||||
return new BrowserResult("Revision", createFileObject());
|
||||
}
|
||||
|
||||
private List<FileObject> createFileObjects() {
|
||||
List<FileObject> fileObjects = new ArrayList<>();
|
||||
private FileObject createFileObject() {
|
||||
FileObject file = new FileObject();
|
||||
file.setName("");
|
||||
file.setPath("/path");
|
||||
file.setDirectory(true);
|
||||
|
||||
fileObjects.add(fileObject1);
|
||||
fileObjects.add(fileObject2);
|
||||
return fileObjects;
|
||||
file.addChild(fileObject1);
|
||||
file.addChild(fileObject2);
|
||||
return file;
|
||||
}
|
||||
|
||||
private void assertEqualAttributes(BrowserResult browserResult, BrowserResultDto dto) {
|
||||
private void assertEqualAttributes(BrowserResult browserResult, FileObjectDto dto) {
|
||||
assertThat(dto.getRevision()).isEqualTo(browserResult.getRevision());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.junit.Test;
|
||||
import sonia.scm.PageResult;
|
||||
import sonia.scm.repository.Changeset;
|
||||
import sonia.scm.repository.Repository;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class ChangesetCollectionToDtoMapperTest {
|
||||
|
||||
public static final Repository REPOSITORY = new Repository("", "git", "space", "name");
|
||||
public static final Changeset CHANGESET = new Changeset();
|
||||
private final ChangesetToChangesetDtoMapper changesetToChangesetDtoMapper = mock(ChangesetToChangesetDtoMapper.class);
|
||||
|
||||
private final ChangesetCollectionToDtoMapper changesetCollectionToDtoMapper = new ChangesetCollectionToDtoMapper(changesetToChangesetDtoMapper, ResourceLinksMock.createMock(URI.create("/")));
|
||||
|
||||
@Test
|
||||
public void shouldMapCollectionEntries() {
|
||||
ChangesetDto expectedChangesetDto = new ChangesetDto();
|
||||
when(changesetToChangesetDtoMapper.map(CHANGESET, REPOSITORY)).thenReturn(expectedChangesetDto);
|
||||
|
||||
CollectionDto collectionDto = changesetCollectionToDtoMapper.map(0, 1, new PageResult<>(asList(CHANGESET), 1), REPOSITORY);
|
||||
|
||||
assertThat(collectionDto.getEmbedded().hasItem("changesets")).isTrue();
|
||||
assertThat(collectionDto.getEmbedded().getItemsBy("changesets")).containsExactly(expectedChangesetDto);
|
||||
assertThat(collectionDto.getEmbedded().hasItem("branch")).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotEmbedBranchIfNotSpecified() {
|
||||
ChangesetDto expectedChangesetDto = new ChangesetDto();
|
||||
when(changesetToChangesetDtoMapper.map(CHANGESET, REPOSITORY)).thenReturn(expectedChangesetDto);
|
||||
|
||||
CollectionDto collectionDto = changesetCollectionToDtoMapper.map(0, 1, new PageResult<>(asList(CHANGESET), 1), REPOSITORY);
|
||||
|
||||
assertThat(collectionDto.getEmbedded().hasItem("branch")).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldEmbedBranchIfSpecified() {
|
||||
ChangesetDto expectedChangesetDto = new ChangesetDto();
|
||||
when(changesetToChangesetDtoMapper.map(CHANGESET, REPOSITORY)).thenReturn(expectedChangesetDto);
|
||||
|
||||
CollectionDto collectionDto = changesetCollectionToDtoMapper.map(0, 1, new PageResult<>(asList(CHANGESET), 1), REPOSITORY, "someBranch");
|
||||
|
||||
assertThat(collectionDto.getEmbedded().hasItem("branch")).isTrue();
|
||||
assertThat(collectionDto.getEmbedded().getItemsBy("branch"))
|
||||
.hasSize(1)
|
||||
.first().matches(b -> b.getLinks().getLinkBy("self").isPresent())
|
||||
.extracting(b -> b.getLinks().getLinkBy("self").get().getHref()).first().isEqualTo("/v2/repositories/space/name/branches/someBranch");
|
||||
assertThat(collectionDto.getEmbedded().getItemsBy("branch"))
|
||||
.first().extracting("name").first().isEqualTo("someBranch");
|
||||
}
|
||||
}
|
||||
@@ -109,8 +109,8 @@ public class ChangesetRootResourceTest extends RepositoryTestBase {
|
||||
List<Changeset> changesetList = Lists.newArrayList(new Changeset(id, Date.from(creationDate).getTime(), new Person(authorName, authorEmail), commit));
|
||||
when(changesetPagingResult.getChangesets()).thenReturn(changesetList);
|
||||
when(changesetPagingResult.getTotal()).thenReturn(1);
|
||||
when(logCommandBuilder.setPagingStart(anyInt())).thenReturn(logCommandBuilder);
|
||||
when(logCommandBuilder.setPagingLimit(anyInt())).thenReturn(logCommandBuilder);
|
||||
when(logCommandBuilder.setPagingStart(0)).thenReturn(logCommandBuilder);
|
||||
when(logCommandBuilder.setPagingLimit(10)).thenReturn(logCommandBuilder);
|
||||
when(logCommandBuilder.setBranch(anyString())).thenReturn(logCommandBuilder);
|
||||
when(logCommandBuilder.getChangesets()).thenReturn(changesetPagingResult);
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
@@ -126,6 +126,34 @@ public class ChangesetRootResourceTest extends RepositoryTestBase {
|
||||
assertTrue(response.getContentAsString().contains(String.format("\"description\":\"%s\"", commit)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldGetSinglePageOfChangeSets() throws Exception {
|
||||
String id = "revision_123";
|
||||
Instant creationDate = Instant.now();
|
||||
String authorName = "name";
|
||||
String authorEmail = "em@i.l";
|
||||
String commit = "my branch commit";
|
||||
ChangesetPagingResult changesetPagingResult = mock(ChangesetPagingResult.class);
|
||||
List<Changeset> changesetList = Lists.newArrayList(new Changeset(id, Date.from(creationDate).getTime(), new Person(authorName, authorEmail), commit));
|
||||
when(changesetPagingResult.getChangesets()).thenReturn(changesetList);
|
||||
when(changesetPagingResult.getTotal()).thenReturn(1);
|
||||
when(logCommandBuilder.setPagingStart(20)).thenReturn(logCommandBuilder);
|
||||
when(logCommandBuilder.setPagingLimit(10)).thenReturn(logCommandBuilder);
|
||||
when(logCommandBuilder.setBranch(anyString())).thenReturn(logCommandBuilder);
|
||||
when(logCommandBuilder.getChangesets()).thenReturn(changesetPagingResult);
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.get(CHANGESET_URL + "?page=2")
|
||||
.accept(VndMediaType.CHANGESET_COLLECTION);
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
dispatcher.invoke(request, response);
|
||||
assertEquals(200, response.getStatus());
|
||||
log.info("Response :{}", response.getContentAsString());
|
||||
assertTrue(response.getContentAsString().contains(String.format("\"id\":\"%s\"", id)));
|
||||
assertTrue(response.getContentAsString().contains(String.format("\"name\":\"%s\"", authorName)));
|
||||
assertTrue(response.getContentAsString().contains(String.format("\"mail\":\"%s\"", authorEmail)));
|
||||
assertTrue(response.getContentAsString().contains(String.format("\"description\":\"%s\"", commit)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldGetChangeSet() throws Exception {
|
||||
String id = "revision_123";
|
||||
@@ -137,8 +165,6 @@ public class ChangesetRootResourceTest extends RepositoryTestBase {
|
||||
List<Changeset> changesetList = Lists.newArrayList(new Changeset(id, Date.from(creationDate).getTime(), new Person(authorName, authorEmail), commit));
|
||||
when(changesetPagingResult.getChangesets()).thenReturn(changesetList);
|
||||
when(changesetPagingResult.getTotal()).thenReturn(1);
|
||||
when(logCommandBuilder.setPagingStart(anyInt())).thenReturn(logCommandBuilder);
|
||||
when(logCommandBuilder.setPagingLimit(anyInt())).thenReturn(logCommandBuilder);
|
||||
when(logCommandBuilder.setEndChangeset(anyString())).thenReturn(logCommandBuilder);
|
||||
when(logCommandBuilder.setStartChangeset(anyString())).thenReturn(logCommandBuilder);
|
||||
when(logCommandBuilder.getChangesets()).thenReturn(changesetPagingResult);
|
||||
|
||||
@@ -5,6 +5,7 @@ import org.jboss.resteasy.mock.MockDispatcherFactory;
|
||||
import sonia.scm.api.rest.AlreadyExistsExceptionMapper;
|
||||
import sonia.scm.api.rest.AuthorizationExceptionMapper;
|
||||
import sonia.scm.api.rest.ConcurrentModificationExceptionMapper;
|
||||
import sonia.scm.api.rest.IllegalArgumentExceptionMapper;
|
||||
|
||||
public class DispatcherMock {
|
||||
public static Dispatcher createDispatcher(Object resource) {
|
||||
@@ -17,6 +18,7 @@ public class DispatcherMock {
|
||||
dispatcher.getProviderFactory().registerProvider(InternalRepositoryExceptionMapper.class);
|
||||
dispatcher.getProviderFactory().registerProvider(ChangePasswordNotAllowedExceptionMapper.class);
|
||||
dispatcher.getProviderFactory().registerProvider(InvalidPasswordExceptionMapper.class);
|
||||
dispatcher.getProviderFactory().registerProvider(IllegalArgumentExceptionMapper.class);
|
||||
return dispatcher;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import java.util.Optional;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@SubjectAware(configuration = "classpath:sonia/scm/shiro-001.ini")
|
||||
@SubjectAware(configuration = "classpath:sonia/scm/shiro-002.ini")
|
||||
public class IndexResourceTest {
|
||||
|
||||
@Rule
|
||||
@@ -94,6 +94,26 @@ public class IndexResourceTest {
|
||||
Assertions.assertThat(index.getLinks().getLinkBy("config")).matches(o -> !o.isPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SubjectAware(username = "trillian", password = "secret")
|
||||
public void shouldRenderAutoCompleteLinks() {
|
||||
IndexDto index = indexResource.getIndex();
|
||||
|
||||
Assertions.assertThat(index.getLinks().getLinksBy("autocomplete"))
|
||||
.extracting("name")
|
||||
.containsExactlyInAnyOrder("users", "groups");
|
||||
}
|
||||
|
||||
@Test
|
||||
@SubjectAware(username = "user_without_autocomplete_permission", password = "secret")
|
||||
public void userWithoutAutocompletePermissionShouldNotSeeAutoCompleteLinks() {
|
||||
IndexDto index = indexResource.getIndex();
|
||||
|
||||
Assertions.assertThat(index.getLinks().getLinksBy("autocomplete"))
|
||||
.extracting("name")
|
||||
.doesNotContainSequence("users", "groups");
|
||||
}
|
||||
|
||||
@Test
|
||||
@SubjectAware(username = "dent", password = "secret")
|
||||
public void shouldRenderAdminLinksIfAuthorized() {
|
||||
|
||||
@@ -13,10 +13,12 @@ import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import sonia.scm.user.InvalidPasswordException;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.user.UserManager;
|
||||
import sonia.scm.web.VndMediaType;
|
||||
|
||||
import javax.lang.model.util.Types;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
@@ -26,6 +28,7 @@ import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.mockito.MockitoAnnotations.initMocks;
|
||||
@@ -69,7 +72,6 @@ public class MeResourceTest {
|
||||
doNothing().when(userManager).modify(userCaptor.capture());
|
||||
doNothing().when(userManager).delete(userCaptor.capture());
|
||||
when(userManager.isTypeDefault(userCaptor.capture())).thenCallRealMethod();
|
||||
when(userManager.getUserTypeChecker()).thenCallRealMethod();
|
||||
when(userManager.getDefaultType()).thenReturn("xml");
|
||||
MeResource meResource = new MeResource(userToDtoMapper, userManager, passwordService);
|
||||
when(uriInfo.getApiRestUri()).thenReturn(URI.create("/"));
|
||||
@@ -97,38 +99,40 @@ public class MeResourceTest {
|
||||
public void shouldEncryptPasswordBeforeChanging() throws Exception {
|
||||
String newPassword = "pwd123";
|
||||
String encryptedNewPassword = "encrypted123";
|
||||
String oldPassword = "notEncriptedSecret";
|
||||
String encryptedOldPassword = "encryptedOld";
|
||||
String oldPassword = "secret";
|
||||
String content = String.format("{ \"oldPassword\": \"%s\" , \"newPassword\": \"%s\" }", oldPassword, newPassword);
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.put("/" + MeResource.ME_PATH_V2 + "password")
|
||||
.contentType(VndMediaType.PASSWORD_CHANGE)
|
||||
.content(content.getBytes());
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
when(passwordService.encryptPassword(eq(newPassword))).thenReturn(encryptedNewPassword);
|
||||
when(passwordService.encryptPassword(eq(oldPassword))).thenReturn("secret");
|
||||
|
||||
when(passwordService.encryptPassword(newPassword)).thenReturn(encryptedNewPassword);
|
||||
when(passwordService.encryptPassword(oldPassword)).thenReturn(encryptedOldPassword);
|
||||
|
||||
ArgumentCaptor<String> encryptedOldPasswordCaptor = ArgumentCaptor.forClass(String.class);
|
||||
ArgumentCaptor<String> encryptedNewPasswordCaptor = ArgumentCaptor.forClass(String.class);
|
||||
doNothing().when(userManager).changePasswordForLoggedInUser(encryptedOldPasswordCaptor.capture(), encryptedNewPasswordCaptor.capture());
|
||||
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
assertEquals(HttpServletResponse.SC_NO_CONTENT, response.getStatus());
|
||||
verify(userManager).modify(any(User.class));
|
||||
User updatedUser = userCaptor.getValue();
|
||||
assertEquals(encryptedNewPassword, updatedUser.getPassword());
|
||||
assertEquals(encryptedNewPassword, encryptedNewPasswordCaptor.getValue());
|
||||
assertEquals(encryptedOldPassword, encryptedOldPasswordCaptor.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SubjectAware(username = "trillian", password = "secret")
|
||||
public void shouldGet400OnChangePasswordOfUserWithNonDefaultType() throws Exception {
|
||||
public void shouldGet400OnMissingOldPassword() throws Exception {
|
||||
originalUser.setType("not an xml type");
|
||||
String newPassword = "pwd123";
|
||||
String oldPassword = "notEncriptedSecret";
|
||||
String content = String.format("{ \"oldPassword\": \"%s\" , \"newPassword\": \"%s\" }", oldPassword, newPassword);
|
||||
String content = String.format("{ \"newPassword\": \"%s\" }", newPassword);
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.put("/" + MeResource.ME_PATH_V2 + "password")
|
||||
.contentType(VndMediaType.PASSWORD_CHANGE)
|
||||
.content(content.getBytes());
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
when(passwordService.encryptPassword(newPassword)).thenReturn("encrypted123");
|
||||
when(passwordService.encryptPassword(eq(oldPassword))).thenReturn("secret");
|
||||
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
@@ -137,17 +141,34 @@ public class MeResourceTest {
|
||||
|
||||
@Test
|
||||
@SubjectAware(username = "trillian", password = "secret")
|
||||
public void shouldGet400OnChangePasswordIfOldPasswordDoesNotMatchOriginalPassword() throws Exception {
|
||||
public void shouldGet400OnMissingEmptyPassword() throws Exception {
|
||||
String newPassword = "pwd123";
|
||||
String oldPassword = "notEncriptedSecret";
|
||||
String oldPassword = "";
|
||||
String content = String.format("{ \"oldPassword\": \"%s\" , \"newPassword\": \"%s\" }", oldPassword, newPassword);
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.put("/" + MeResource.ME_PATH_V2 + "password")
|
||||
.contentType(VndMediaType.PASSWORD_CHANGE)
|
||||
.content(content.getBytes());
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
when(passwordService.encryptPassword(newPassword)).thenReturn("encrypted123");
|
||||
when(passwordService.encryptPassword(eq(oldPassword))).thenReturn("differentThanSecret");
|
||||
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
assertEquals(HttpServletResponse.SC_BAD_REQUEST, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SubjectAware(username = "trillian", password = "secret")
|
||||
public void shouldMapExceptionFromManager() throws Exception {
|
||||
String newPassword = "pwd123";
|
||||
String oldPassword = "secret";
|
||||
String content = String.format("{ \"oldPassword\": \"%s\" , \"newPassword\": \"%s\" }", oldPassword, newPassword);
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.put("/" + MeResource.ME_PATH_V2 + "password")
|
||||
.contentType(VndMediaType.PASSWORD_CHANGE)
|
||||
.content(content.getBytes());
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
|
||||
doThrow(InvalidPasswordException.class).when(userManager).changePasswordForLoggedInUser(any(), any());
|
||||
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ public class ResourceLinksMock {
|
||||
when(resourceLinks.user()).thenReturn(userLinks);
|
||||
when(resourceLinks.me()).thenReturn(new ResourceLinks.MeLinks(uriInfo,userLinks));
|
||||
when(resourceLinks.userCollection()).thenReturn(new ResourceLinks.UserCollectionLinks(uriInfo));
|
||||
when(resourceLinks.autoComplete()).thenReturn(new ResourceLinks.AutoCompleteLinks(uriInfo));
|
||||
when(resourceLinks.group()).thenReturn(new ResourceLinks.GroupLinks(uriInfo));
|
||||
when(resourceLinks.groupCollection()).thenReturn(new ResourceLinks.GroupCollectionLinks(uriInfo));
|
||||
when(resourceLinks.repository()).thenReturn(new ResourceLinks.RepositoryLinks(uriInfo));
|
||||
|
||||
@@ -173,6 +173,30 @@ public class ResourceLinksTest {
|
||||
assertEquals(BASE_URL + ConfigResource.CONFIG_PATH_V2, url);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldHandleSpacesInPaths() {
|
||||
String url = resourceLinks.source().content("space", "name", "rev", "name with spaces");
|
||||
assertEquals(BASE_URL + RepositoryRootResource.REPOSITORIES_PATH_V2 + "space/name/content/rev/name%20with%20spaces", url);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldHandleBackslashInPaths() {
|
||||
String url = resourceLinks.source().content("space", "name", "rev", "name_with_\\");
|
||||
assertEquals(BASE_URL + RepositoryRootResource.REPOSITORIES_PATH_V2 + "space/name/content/rev/name_with_%5C", url);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldHandleNewLineInPaths() {
|
||||
String url = resourceLinks.source().content("space", "name", "rev", "name_with\nnew_line");
|
||||
assertEquals(BASE_URL + RepositoryRootResource.REPOSITORIES_PATH_V2 + "space/name/content/rev/name_with%0Anew_line", url);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldKeepSlashesInInPaths() {
|
||||
String url = resourceLinks.source().content("space", "name", "rev", "some/dir/somewhere");
|
||||
assertEquals(BASE_URL + RepositoryRootResource.REPOSITORIES_PATH_V2 + "space/name/content/rev/some/dir/somewhere", url);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void initUriInfo() {
|
||||
initMocks(this);
|
||||
|
||||
@@ -10,11 +10,11 @@ import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import sonia.scm.NotFoundException;
|
||||
import sonia.scm.repository.BrowserResult;
|
||||
import sonia.scm.repository.FileObject;
|
||||
import sonia.scm.repository.NamespaceAndName;
|
||||
import sonia.scm.repository.RepositoryNotFoundException;
|
||||
import sonia.scm.repository.RevisionNotFoundException;
|
||||
import sonia.scm.repository.api.BrowseCommandBuilder;
|
||||
import sonia.scm.repository.api.RepositoryService;
|
||||
import sonia.scm.repository.api.RepositoryServiceFactory;
|
||||
@@ -22,12 +22,8 @@ import sonia.scm.repository.api.RepositoryServiceFactory;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static sonia.scm.api.v2.resources.DispatcherMock.createDispatcher;
|
||||
|
||||
@@ -46,30 +42,25 @@ public class SourceRootResourceTest extends RepositoryTestBase {
|
||||
@Mock
|
||||
private BrowseCommandBuilder browseCommandBuilder;
|
||||
|
||||
@Mock
|
||||
private FileObjectToFileObjectDtoMapper fileObjectToFileObjectDtoMapper;
|
||||
|
||||
@InjectMocks
|
||||
private BrowserResultToBrowserResultDtoMapper browserResultToBrowserResultDtoMapper;
|
||||
private FileObjectToFileObjectDtoMapperImpl fileObjectToFileObjectDtoMapper;
|
||||
|
||||
private BrowserResultToFileObjectDtoMapper browserResultToFileObjectDtoMapper;
|
||||
|
||||
|
||||
@Before
|
||||
public void prepareEnvironment() throws Exception {
|
||||
browserResultToFileObjectDtoMapper = new BrowserResultToFileObjectDtoMapper(fileObjectToFileObjectDtoMapper);
|
||||
when(serviceFactory.create(new NamespaceAndName("space", "repo"))).thenReturn(service);
|
||||
when(service.getBrowseCommand()).thenReturn(browseCommandBuilder);
|
||||
|
||||
FileObjectDto dto = new FileObjectDto();
|
||||
dto.setName("name");
|
||||
dto.setLength(1024);
|
||||
|
||||
when(fileObjectToFileObjectDtoMapper.map(any(FileObject.class), any(NamespaceAndName.class), anyString())).thenReturn(dto);
|
||||
SourceRootResource sourceRootResource = new SourceRootResource(serviceFactory, browserResultToBrowserResultDtoMapper);
|
||||
SourceRootResource sourceRootResource = new SourceRootResource(serviceFactory, browserResultToFileObjectDtoMapper);
|
||||
super.sourceRootResource = Providers.of(sourceRootResource);
|
||||
dispatcher = createDispatcher(getRepositoryRootResource());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnSources() throws URISyntaxException, IOException, RevisionNotFoundException {
|
||||
public void shouldReturnSources() throws URISyntaxException, IOException, NotFoundException {
|
||||
BrowserResult result = createBrowserResult();
|
||||
when(browseCommandBuilder.getBrowserResult()).thenReturn(result);
|
||||
MockHttpRequest request = MockHttpRequest.get("/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + "space/repo/sources");
|
||||
@@ -77,8 +68,9 @@ public class SourceRootResourceTest extends RepositoryTestBase {
|
||||
|
||||
dispatcher.invoke(request, response);
|
||||
assertThat(response.getStatus()).isEqualTo(200);
|
||||
System.out.println(response.getContentAsString());
|
||||
assertThat(response.getContentAsString()).contains("\"revision\":\"revision\"");
|
||||
assertThat(response.getContentAsString()).contains("\"files\":");
|
||||
assertThat(response.getContentAsString()).contains("\"children\":");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -92,13 +84,11 @@ public class SourceRootResourceTest extends RepositoryTestBase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldGetResultForSingleFile() throws URISyntaxException, IOException, RevisionNotFoundException {
|
||||
BrowserResult browserResult = new BrowserResult();
|
||||
browserResult.setRevision("revision");
|
||||
public void shouldGetResultForSingleFile() throws URISyntaxException, IOException, NotFoundException {
|
||||
FileObject fileObject = new FileObject();
|
||||
fileObject.setName("File Object!");
|
||||
|
||||
browserResult.setFiles(Arrays.asList(fileObject));
|
||||
fileObject.setPath("/");
|
||||
BrowserResult browserResult = new BrowserResult("revision", fileObject);
|
||||
|
||||
when(browseCommandBuilder.getBrowserResult()).thenReturn(browserResult);
|
||||
MockHttpRequest request = MockHttpRequest.get("/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + "space/repo/sources/revision/fileabc");
|
||||
@@ -121,10 +111,15 @@ public class SourceRootResourceTest extends RepositoryTestBase {
|
||||
}
|
||||
|
||||
private BrowserResult createBrowserResult() {
|
||||
return new BrowserResult("revision", "tag", "branch", createFileObjects());
|
||||
return new BrowserResult("revision", createFileObject());
|
||||
}
|
||||
|
||||
private List<FileObject> createFileObjects() {
|
||||
private FileObject createFileObject() {
|
||||
FileObject parent = new FileObject();
|
||||
parent.setName("bar");
|
||||
parent.setPath("/foo/bar");
|
||||
parent.setDirectory(true);
|
||||
|
||||
FileObject fileObject1 = new FileObject();
|
||||
fileObject1.setName("FO 1");
|
||||
fileObject1.setDirectory(false);
|
||||
@@ -132,6 +127,7 @@ public class SourceRootResourceTest extends RepositoryTestBase {
|
||||
fileObject1.setPath("/foo/bar/fo1");
|
||||
fileObject1.setLength(1024L);
|
||||
fileObject1.setLastModified(0L);
|
||||
parent.addChild(fileObject1);
|
||||
|
||||
FileObject fileObject2 = new FileObject();
|
||||
fileObject2.setName("FO 2");
|
||||
@@ -140,7 +136,8 @@ public class SourceRootResourceTest extends RepositoryTestBase {
|
||||
fileObject2.setPath("/foo/bar/fo2");
|
||||
fileObject2.setLength(4096L);
|
||||
fileObject2.setLastModified(1234L);
|
||||
parent.addChild(fileObject2);
|
||||
|
||||
return Arrays.asList(fileObject1, fileObject2);
|
||||
return parent;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,9 @@ import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import sonia.scm.NotFoundException;
|
||||
import sonia.scm.PageResult;
|
||||
import sonia.scm.user.ChangePasswordNotAllowedException;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.user.UserManager;
|
||||
import sonia.scm.web.VndMediaType;
|
||||
@@ -23,7 +25,6 @@ import javax.servlet.http.HttpServletResponse;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.text.MessageFormat;
|
||||
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
@@ -32,6 +33,7 @@ import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
@@ -70,7 +72,6 @@ public class UserRootResourceTest {
|
||||
originalUser = createDummyUser("Neo");
|
||||
when(userManager.create(userCaptor.capture())).thenAnswer(invocation -> invocation.getArguments()[0]);
|
||||
when(userManager.isTypeDefault(userCaptor.capture())).thenCallRealMethod();
|
||||
when(userManager.getUserTypeChecker()).thenCallRealMethod();
|
||||
doNothing().when(userManager).modify(userCaptor.capture());
|
||||
doNothing().when(userManager).delete(userCaptor.capture());
|
||||
when(userManager.getDefaultType()).thenReturn("xml");
|
||||
@@ -144,7 +145,7 @@ public class UserRootResourceTest {
|
||||
String content = String.format("{\"newPassword\": \"%s\"}", newPassword);
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.put("/" + UserRootResource.USERS_PATH_V2 + "Neo/password")
|
||||
.contentType(VndMediaType.PASSWORD_CHANGE)
|
||||
.contentType(VndMediaType.PASSWORD_OVERWRITE)
|
||||
.content(content.getBytes());
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
when(passwordService.encryptPassword(newPassword)).thenReturn("encrypted123");
|
||||
@@ -152,26 +153,61 @@ public class UserRootResourceTest {
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
assertEquals(HttpServletResponse.SC_NO_CONTENT, response.getStatus());
|
||||
verify(userManager).modify(any(User.class));
|
||||
User updatedUser = userCaptor.getValue();
|
||||
assertEquals("encrypted123", updatedUser.getPassword());
|
||||
verify(userManager).overwritePassword("Neo", "encrypted123");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldGet400OnChangePasswordOfUserWithNonDefaultType() throws Exception {
|
||||
public void shouldGet400OnOverwritePasswordWhenManagerThrowsNotAllowed() throws Exception {
|
||||
originalUser.setType("not an xml type");
|
||||
String newPassword = "pwd123";
|
||||
String content = String.format("{\"newPassword\": \"%s\"}", newPassword);
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.put("/" + UserRootResource.USERS_PATH_V2 + "Neo/password")
|
||||
.contentType(VndMediaType.PASSWORD_CHANGE)
|
||||
.contentType(VndMediaType.PASSWORD_OVERWRITE)
|
||||
.content(content.getBytes());
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
|
||||
doThrow(ChangePasswordNotAllowedException.class).when(userManager).overwritePassword(any(), any());
|
||||
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
assertEquals(HttpServletResponse.SC_BAD_REQUEST, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldGet404OnOverwritePasswordWhenNotFound() throws Exception {
|
||||
originalUser.setType("not an xml type");
|
||||
String newPassword = "pwd123";
|
||||
String content = String.format("{\"newPassword\": \"%s\"}", newPassword);
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.put("/" + UserRootResource.USERS_PATH_V2 + "Neo/password")
|
||||
.contentType(VndMediaType.PASSWORD_OVERWRITE)
|
||||
.content(content.getBytes());
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
|
||||
doThrow(NotFoundException.class).when(userManager).overwritePassword(any(), any());
|
||||
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
assertEquals(HttpServletResponse.SC_NOT_FOUND, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldEncryptPasswordOnOverwritePassword() throws Exception {
|
||||
originalUser.setType("not an xml type");
|
||||
String newPassword = "pwd123";
|
||||
String content = String.format("{\"newPassword\": \"%s\"}", newPassword);
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.put("/" + UserRootResource.USERS_PATH_V2 + "Neo/password")
|
||||
.contentType(VndMediaType.PASSWORD_OVERWRITE)
|
||||
.content(content.getBytes());
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
when(passwordService.encryptPassword(newPassword)).thenReturn("encrypted123");
|
||||
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
assertEquals(HttpServletResponse.SC_BAD_REQUEST, response.getStatus());
|
||||
assertEquals(HttpServletResponse.SC_NO_CONTENT, response.getStatus());
|
||||
verify(userManager).overwritePassword("Neo", "encrypted123");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -65,7 +65,7 @@ public class UserToUserDtoMapperTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldGetPasswordLinkOnlyForDefaultUserType() {
|
||||
public void shouldGetPasswordLinkForAdmin() {
|
||||
User user = createDefaultUser();
|
||||
when(subject.isPermitted("user:modify:abc")).thenReturn(true);
|
||||
when(userManager.isTypeDefault(eq(user))).thenReturn(true);
|
||||
@@ -73,14 +73,15 @@ public class UserToUserDtoMapperTest {
|
||||
UserDto userDto = mapper.map(user);
|
||||
|
||||
assertEquals("expected password link with modify permission", expectedBaseUri.resolve("abc/password").toString(), userDto.getLinks().getLinkBy("password").get().getHref());
|
||||
}
|
||||
|
||||
when(subject.isPermitted("user:modify:abc")).thenReturn(false);
|
||||
userDto = mapper.map(user);
|
||||
assertEquals("expected password link on mission modify permission", expectedBaseUri.resolve("abc/password").toString(), userDto.getLinks().getLinkBy("password").get().getHref());
|
||||
|
||||
@Test
|
||||
public void shouldGetPasswordLinkOnlyForDefaultUserType() {
|
||||
User user = createDefaultUser();
|
||||
when(subject.isPermitted("user:modify:abc")).thenReturn(true);
|
||||
when(userManager.isTypeDefault(eq(user))).thenReturn(false);
|
||||
|
||||
userDto = mapper.map(user);
|
||||
UserDto userDto = mapper.map(user);
|
||||
|
||||
assertFalse("expected no password link", userDto.getLinks().getLinkBy("password").isPresent());
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase<Repository> {
|
||||
}
|
||||
|
||||
@Test(expected = NotFoundException.class)
|
||||
public void testDeleteNotFound() throws NotFoundException {
|
||||
public void testDeleteNotFound(){
|
||||
manager.delete(createRepositoryWithId());
|
||||
}
|
||||
|
||||
@@ -304,7 +304,7 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase<Repository> {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testModify() throws NotFoundException, AlreadyExistsException {
|
||||
public void testModify() throws AlreadyExistsException {
|
||||
Repository heartOfGold = createTestRepository();
|
||||
|
||||
heartOfGold.setDescription("prototype ship");
|
||||
@@ -328,12 +328,12 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase<Repository> {
|
||||
}
|
||||
|
||||
@Test(expected = NotFoundException.class)
|
||||
public void testModifyNotFound() throws NotFoundException {
|
||||
public void testModifyNotFound(){
|
||||
manager.modify(createRepositoryWithId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRefresh() throws NotFoundException, AlreadyExistsException {
|
||||
public void testRefresh() throws AlreadyExistsException {
|
||||
Repository heartOfGold = createTestRepository();
|
||||
String description = heartOfGold.getDescription();
|
||||
|
||||
@@ -354,7 +354,7 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase<Repository> {
|
||||
}
|
||||
|
||||
@Test(expected = RepositoryNotFoundException.class)
|
||||
public void testRefreshNotFound() throws NotFoundException {
|
||||
public void testRefreshNotFound(){
|
||||
manager.refresh(createRepositoryWithId());
|
||||
}
|
||||
|
||||
@@ -495,7 +495,7 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase<Repository> {
|
||||
return createRepository(RepositoryTestData.createHeartOfGold());
|
||||
}
|
||||
|
||||
private void delete(Manager<Repository> manager, Repository repository) throws NotFoundException {
|
||||
private void delete(Manager<Repository> manager, Repository repository){
|
||||
|
||||
String id = repository.getId();
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/**
|
||||
* Copyright (c) 2014, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
@@ -13,7 +13,7 @@
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
@@ -24,9 +24,9 @@
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package sonia.scm.security;
|
||||
@@ -57,7 +57,6 @@ import sonia.scm.repository.RepositoryTestData;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.user.UserTestData;
|
||||
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
@@ -70,7 +69,7 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link AuthorizationCollector}.
|
||||
*
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -79,28 +78,28 @@ public class DefaultAuthorizationCollectorTest {
|
||||
|
||||
@Mock
|
||||
private Cache cache;
|
||||
|
||||
|
||||
@Mock
|
||||
private CacheManager cacheManager;
|
||||
|
||||
|
||||
@Mock
|
||||
private RepositoryDAO repositoryDAO;
|
||||
|
||||
@Mock
|
||||
private SecuritySystem securitySystem;
|
||||
|
||||
|
||||
private DefaultAuthorizationCollector collector;
|
||||
|
||||
|
||||
@Rule
|
||||
public ShiroRule shiro = new ShiroRule();
|
||||
|
||||
|
||||
/**
|
||||
* Set up object to test.
|
||||
*/
|
||||
@Before
|
||||
public void setUp(){
|
||||
when(cacheManager.getCache(Mockito.any(String.class))).thenReturn(cache);
|
||||
|
||||
|
||||
collector = new DefaultAuthorizationCollector(cacheManager, repositoryDAO, securitySystem);
|
||||
}
|
||||
|
||||
@@ -116,7 +115,7 @@ public class DefaultAuthorizationCollectorTest {
|
||||
assertThat(authInfo.getStringPermissions(), nullValue());
|
||||
assertThat(authInfo.getObjectPermissions(), nullValue());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link AuthorizationCollector#collect()} from cache.
|
||||
*/
|
||||
@@ -124,16 +123,15 @@ public class DefaultAuthorizationCollectorTest {
|
||||
@SubjectAware(
|
||||
configuration = "classpath:sonia/scm/shiro-001.ini"
|
||||
)
|
||||
public void testCollectFromCache()
|
||||
{
|
||||
public void testCollectFromCache() {
|
||||
AuthorizationInfo info = new SimpleAuthorizationInfo();
|
||||
when(cache.get(anyObject())).thenReturn(info);
|
||||
authenticate(UserTestData.createTrillian(), "main");
|
||||
|
||||
|
||||
AuthorizationInfo authInfo = collector.collect();
|
||||
assertSame(info, authInfo);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link AuthorizationCollector#collect()} with cache.
|
||||
*/
|
||||
@@ -141,13 +139,13 @@ public class DefaultAuthorizationCollectorTest {
|
||||
@SubjectAware(
|
||||
configuration = "classpath:sonia/scm/shiro-001.ini"
|
||||
)
|
||||
public void testCollectWithCache(){
|
||||
public void testCollectWithCache() {
|
||||
authenticate(UserTestData.createTrillian(), "main");
|
||||
|
||||
|
||||
AuthorizationInfo authInfo = collector.collect();
|
||||
verify(cache).put(any(), any());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link AuthorizationCollector#collect()} without permissions.
|
||||
*/
|
||||
@@ -155,17 +153,16 @@ public class DefaultAuthorizationCollectorTest {
|
||||
@SubjectAware(
|
||||
configuration = "classpath:sonia/scm/shiro-001.ini"
|
||||
)
|
||||
public void testCollectWithoutPermissions()
|
||||
{
|
||||
public void testCollectWithoutPermissions() {
|
||||
authenticate(UserTestData.createTrillian(), "main");
|
||||
|
||||
|
||||
AuthorizationInfo authInfo = collector.collect();
|
||||
assertThat(authInfo.getRoles(), Matchers.contains(Role.USER));
|
||||
assertThat(authInfo.getStringPermissions(), hasSize(1));
|
||||
assertThat(authInfo.getStringPermissions(), contains("user:read:trillian"));
|
||||
assertThat(authInfo.getStringPermissions(), hasSize(4));
|
||||
assertThat(authInfo.getStringPermissions(), containsInAnyOrder("user:autocomplete", "group:autocomplete", "user:changePassword:trillian", "user:read:trillian"));
|
||||
assertThat(authInfo.getObjectPermissions(), nullValue());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link AuthorizationCollector#collect()} as admin.
|
||||
*/
|
||||
@@ -173,18 +170,17 @@ public class DefaultAuthorizationCollectorTest {
|
||||
@SubjectAware(
|
||||
configuration = "classpath:sonia/scm/shiro-001.ini"
|
||||
)
|
||||
public void testCollectAsAdmin()
|
||||
{
|
||||
public void testCollectAsAdmin() {
|
||||
User trillian = UserTestData.createTrillian();
|
||||
trillian.setAdmin(true);
|
||||
authenticate(trillian, "main");
|
||||
|
||||
|
||||
AuthorizationInfo authInfo = collector.collect();
|
||||
assertThat(authInfo.getRoles(), Matchers.containsInAnyOrder(Role.USER, Role.ADMIN));
|
||||
assertThat(authInfo.getObjectPermissions(), nullValue());
|
||||
assertThat(authInfo.getStringPermissions(), Matchers.contains("*"));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link AuthorizationCollector#collect()} with repository permissions.
|
||||
*/
|
||||
@@ -192,8 +188,7 @@ public class DefaultAuthorizationCollectorTest {
|
||||
@SubjectAware(
|
||||
configuration = "classpath:sonia/scm/shiro-001.ini"
|
||||
)
|
||||
public void testCollectWithRepositoryPermissions()
|
||||
{
|
||||
public void testCollectWithRepositoryPermissions() {
|
||||
String group = "heart-of-gold-crew";
|
||||
authenticate(UserTestData.createTrillian(), group);
|
||||
Repository heartOfGold = RepositoryTestData.createHeartOfGold();
|
||||
@@ -204,14 +199,14 @@ public class DefaultAuthorizationCollectorTest {
|
||||
sonia.scm.repository.Permission permission = new sonia.scm.repository.Permission(group, PermissionType.WRITE, true);
|
||||
puzzle42.setPermissions(Lists.newArrayList(permission));
|
||||
when(repositoryDAO.getAll()).thenReturn(Lists.newArrayList(heartOfGold, puzzle42));
|
||||
|
||||
|
||||
// execute and assert
|
||||
AuthorizationInfo authInfo = collector.collect();
|
||||
assertThat(authInfo.getRoles(), Matchers.containsInAnyOrder(Role.USER));
|
||||
assertThat(authInfo.getObjectPermissions(), nullValue());
|
||||
assertThat(authInfo.getStringPermissions(), containsInAnyOrder("repository:read,pull:one", "repository:read,pull,push:two", "user:read:trillian"));
|
||||
assertThat(authInfo.getStringPermissions(), containsInAnyOrder("user:autocomplete", "group:autocomplete", "user:changePassword:trillian", "repository:read,pull:one", "repository:read,pull,push:two", "user:read:trillian"));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link AuthorizationCollector#collect()} with global permissions.
|
||||
*/
|
||||
@@ -219,20 +214,20 @@ public class DefaultAuthorizationCollectorTest {
|
||||
@SubjectAware(
|
||||
configuration = "classpath:sonia/scm/shiro-001.ini"
|
||||
)
|
||||
public void testCollectWithGlobalPermissions(){
|
||||
public void testCollectWithGlobalPermissions() {
|
||||
authenticate(UserTestData.createTrillian(), "main");
|
||||
|
||||
|
||||
StoredAssignedPermission p1 = new StoredAssignedPermission("one", new AssignedPermission("one", "one:one"));
|
||||
StoredAssignedPermission p2 = new StoredAssignedPermission("two", new AssignedPermission("two", "two:two"));
|
||||
when(securitySystem.getPermissions(Mockito.any(Predicate.class))).thenReturn(Lists.newArrayList(p1, p2));
|
||||
|
||||
|
||||
// execute and assert
|
||||
AuthorizationInfo authInfo = collector.collect();
|
||||
assertThat(authInfo.getRoles(), Matchers.containsInAnyOrder(Role.USER));
|
||||
assertThat(authInfo.getObjectPermissions(), nullValue());
|
||||
assertThat(authInfo.getStringPermissions(), containsInAnyOrder("one:one", "two:two", "user:read:trillian"));
|
||||
assertThat(authInfo.getStringPermissions(), containsInAnyOrder("one:one", "two:two", "user:read:trillian", "user:autocomplete", "group:autocomplete", "user:changePassword:trillian"));
|
||||
}
|
||||
|
||||
|
||||
private void authenticate(User user, String group, String... groups) {
|
||||
SimplePrincipalCollection spc = new SimplePrincipalCollection();
|
||||
spc.add(user.getName(), "unit");
|
||||
@@ -249,9 +244,9 @@ public class DefaultAuthorizationCollectorTest {
|
||||
public void testInvalidateCache() {
|
||||
collector.invalidateCache(AuthorizationChangedEvent.createForEveryUser());
|
||||
verify(cache).clear();
|
||||
|
||||
|
||||
collector.invalidateCache(AuthorizationChangedEvent.createForUser("dent"));
|
||||
verify(cache).removeAll(Mockito.any(Predicate.class));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -39,9 +39,13 @@ import com.github.sdorra.shiro.ShiroRule;
|
||||
import com.github.sdorra.shiro.SubjectAware;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import sonia.scm.NotFoundException;
|
||||
import sonia.scm.store.JAXBConfigurationStoreFactory;
|
||||
import sonia.scm.user.xml.XmlUserDAO;
|
||||
import sonia.scm.util.MockUtil;
|
||||
@@ -70,6 +74,10 @@ public class DefaultUserManagerTest extends UserManagerTestBase
|
||||
@Rule
|
||||
public ShiroRule shiro = new ShiroRule();
|
||||
|
||||
|
||||
private UserDAO userDAO = mock(UserDAO.class);
|
||||
private User trillian;
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
@@ -82,6 +90,16 @@ public class DefaultUserManagerTest extends UserManagerTestBase
|
||||
return new DefaultUserManager(createXmlUserDAO());
|
||||
}
|
||||
|
||||
@Before
|
||||
public void initDao() {
|
||||
trillian = UserTestData.createTrillian();
|
||||
trillian.setPassword("oldEncrypted");
|
||||
|
||||
userDAO = mock(UserDAO.class);
|
||||
when(userDAO.getType()).thenReturn("xml");
|
||||
when(userDAO.get("trillian")).thenReturn(trillian);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
@@ -89,7 +107,6 @@ public class DefaultUserManagerTest extends UserManagerTestBase
|
||||
@Test
|
||||
public void testDefaultAccountAfterFristStart()
|
||||
{
|
||||
UserDAO userDAO = mock(UserDAO.class);
|
||||
List<User> users = Lists.newArrayList(new User("tuser"));
|
||||
|
||||
when(userDAO.getAll()).thenReturn(users);
|
||||
@@ -108,8 +125,6 @@ public class DefaultUserManagerTest extends UserManagerTestBase
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testDefaultAccountCreation()
|
||||
{
|
||||
UserDAO userDAO = mock(UserDAO.class);
|
||||
|
||||
when(userDAO.getAll()).thenReturn(Collections.EMPTY_LIST);
|
||||
|
||||
UserManager userManager = new DefaultUserManager(userDAO);
|
||||
@@ -118,6 +133,55 @@ public class DefaultUserManagerTest extends UserManagerTestBase
|
||||
verify(userDAO, times(2)).add(any(User.class));
|
||||
}
|
||||
|
||||
@Test(expected = InvalidPasswordException.class)
|
||||
public void shouldFailChangePasswordForWrongOldPassword() {
|
||||
UserManager userManager = new DefaultUserManager(userDAO);
|
||||
|
||||
userManager.changePasswordForLoggedInUser("wrongPassword", "---");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldSucceedChangePassword() {
|
||||
ArgumentCaptor<User> userCaptor = ArgumentCaptor.forClass(User.class);
|
||||
|
||||
doNothing().when(userDAO).modify(userCaptor.capture());
|
||||
|
||||
UserManager userManager = new DefaultUserManager(userDAO);
|
||||
|
||||
userManager.changePasswordForLoggedInUser("oldEncrypted", "newEncrypted");
|
||||
|
||||
Assertions.assertThat(userCaptor.getValue().getPassword()).isEqualTo("newEncrypted");
|
||||
}
|
||||
|
||||
@Test(expected = ChangePasswordNotAllowedException.class)
|
||||
public void shouldFailOverwritePasswordForWrongType() {
|
||||
trillian.setType("wrongType");
|
||||
|
||||
UserManager userManager = new DefaultUserManager(userDAO);
|
||||
|
||||
userManager.overwritePassword("trillian", "---");
|
||||
}
|
||||
|
||||
@Test(expected = NotFoundException.class)
|
||||
public void shouldFailOverwritePasswordForMissingUser() {
|
||||
UserManager userManager = new DefaultUserManager(userDAO);
|
||||
|
||||
userManager.overwritePassword("notExisting", "---");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldSucceedOverwritePassword() {
|
||||
ArgumentCaptor<User> userCaptor = ArgumentCaptor.forClass(User.class);
|
||||
|
||||
doNothing().when(userDAO).modify(userCaptor.capture());
|
||||
|
||||
UserManager userManager = new DefaultUserManager(userDAO);
|
||||
|
||||
userManager.overwritePassword("trillian", "newEncrypted");
|
||||
|
||||
Assertions.assertThat(userCaptor.getValue().getPassword()).isEqualTo("newEncrypted");
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
private XmlUserDAO createXmlUserDAO() {
|
||||
|
||||
255
scm-webapp/src/test/java/sonia/scm/web/i18n/I18nServletTest.java
Normal file
255
scm-webapp/src/test/java/sonia/scm/web/i18n/I18nServletTest.java
Normal file
@@ -0,0 +1,255 @@
|
||||
package sonia.scm.web.i18n;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.github.sdorra.shiro.ShiroRule;
|
||||
import com.github.sdorra.shiro.SubjectAware;
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.io.Files;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.assertj.core.util.Lists;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockSettings;
|
||||
import org.mockito.internal.creation.MockSettingsImpl;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import sonia.scm.boot.RestartEvent;
|
||||
import sonia.scm.cache.Cache;
|
||||
import sonia.scm.cache.CacheManager;
|
||||
import sonia.scm.event.ScmEventBus;
|
||||
import sonia.scm.plugin.PluginLoader;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.Silent.class)
|
||||
@SubjectAware(configuration = "classpath:sonia/scm/shiro-001.ini")
|
||||
public class I18nServletTest {
|
||||
|
||||
@Rule
|
||||
public ShiroRule shiro = new ShiroRule();
|
||||
|
||||
private static final String GIT_PLUGIN_JSON = json(
|
||||
"{",
|
||||
"'scm-git-plugin': {",
|
||||
"'information': {",
|
||||
"'clone' : 'Clone',",
|
||||
"'create' : 'Create',",
|
||||
"'replace' : 'Push'",
|
||||
"}",
|
||||
"}",
|
||||
"}"
|
||||
);
|
||||
private static final String HG_PLUGIN_JSON = json(
|
||||
"{",
|
||||
"'scm-hg-plugin': {",
|
||||
"'information': {",
|
||||
"'clone' : 'Clone',",
|
||||
"'create' : 'Create',",
|
||||
"'replace' : 'Push'",
|
||||
"}",
|
||||
"}",
|
||||
"}"
|
||||
);
|
||||
private static String SVN_PLUGIN_JSON = json(
|
||||
"{",
|
||||
"'scm-svn-plugin': {",
|
||||
"'information': {",
|
||||
"'checkout' : 'Checkout'",
|
||||
"}",
|
||||
"}",
|
||||
"}"
|
||||
);
|
||||
|
||||
private static String json(String... parts) {
|
||||
return String.join("\n", parts ).replaceAll("'", "\"");
|
||||
}
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder temporaryFolder = new TemporaryFolder();
|
||||
|
||||
@Mock
|
||||
PluginLoader pluginLoader;
|
||||
|
||||
@Mock
|
||||
CacheManager cacheManager;
|
||||
|
||||
@Mock
|
||||
ClassLoader classLoader;
|
||||
|
||||
I18nServlet servlet;
|
||||
|
||||
@Mock
|
||||
private Cache cache;
|
||||
private Enumeration<URL> resources;
|
||||
|
||||
@Before
|
||||
@SuppressWarnings("unchecked")
|
||||
public void init() throws IOException {
|
||||
resources = Collections.enumeration(Lists.newArrayList(
|
||||
createFileFromString(SVN_PLUGIN_JSON).toURL(),
|
||||
createFileFromString(GIT_PLUGIN_JSON).toURL(),
|
||||
createFileFromString(HG_PLUGIN_JSON).toURL()
|
||||
));
|
||||
when(pluginLoader.getUberClassLoader()).thenReturn(classLoader);
|
||||
when(cacheManager.getCache(I18nServlet.CACHE_NAME)).thenReturn(cache);
|
||||
MockSettings settings = new MockSettingsImpl<>();
|
||||
settings.useConstructor(pluginLoader, cacheManager);
|
||||
settings.defaultAnswer(InvocationOnMock::callRealMethod);
|
||||
servlet = mock(I18nServlet.class, settings);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldCleanCacheOnRestartEvent() {
|
||||
ScmEventBus.getInstance().register(servlet);
|
||||
|
||||
ScmEventBus.getInstance().post(new RestartEvent(I18nServlet.class, "Restart to reload the plugin resources"));
|
||||
|
||||
verify(cache).clear();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void shouldFailWith404OnMissingResources() throws IOException {
|
||||
String path = "/locales/de/plugins.json";
|
||||
HttpServletRequest request = mock(HttpServletRequest.class);
|
||||
HttpServletResponse response = mock(HttpServletResponse.class);
|
||||
PrintWriter writer = mock(PrintWriter.class);
|
||||
when(response.getWriter()).thenReturn(writer);
|
||||
when(request.getServletPath()).thenReturn(path);
|
||||
when(classLoader.getResources("locales/de/plugins.json")).thenThrow(IOException.class);
|
||||
|
||||
servlet.doGet(request, response);
|
||||
|
||||
verify(response).setStatus(404);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void shouldFailWith500OnIOException() throws IOException {
|
||||
HttpServletRequest request = mock(HttpServletRequest.class);
|
||||
HttpServletResponse response = mock(HttpServletResponse.class);
|
||||
doThrow(IOException.class).when(response).getWriter();
|
||||
|
||||
servlet.doGet(request, response);
|
||||
|
||||
verify(response).setStatus(500);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void inDevelopmentStageShouldNotUseCache() throws IOException {
|
||||
String path = "/locales/de/plugins.json";
|
||||
when(servlet.isProductionStage()).thenReturn(false);
|
||||
HttpServletRequest request = mock(HttpServletRequest.class);
|
||||
HttpServletResponse response = mock(HttpServletResponse.class);
|
||||
File file = temporaryFolder.newFile();
|
||||
PrintWriter writer = new PrintWriter(new FileOutputStream(file));
|
||||
when(response.getWriter()).thenReturn(writer);
|
||||
when(request.getServletPath()).thenReturn(path);
|
||||
when(classLoader.getResources("locales/de/plugins.json")).thenReturn(resources);
|
||||
|
||||
servlet.doGet(request, response);
|
||||
|
||||
String json = Files.readLines(file, Charset.defaultCharset()).get(0);
|
||||
assertJson(json);
|
||||
verify(cache, never()).get(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void inProductionStageShouldUseCache() throws IOException {
|
||||
String path = "/locales/de/plugins.json";
|
||||
when(servlet.isProductionStage()).thenReturn(true);
|
||||
HttpServletRequest request = mock(HttpServletRequest.class);
|
||||
HttpServletResponse response = mock(HttpServletResponse.class);
|
||||
File file = temporaryFolder.newFile();
|
||||
PrintWriter writer = new PrintWriter(new FileOutputStream(file));
|
||||
when(response.getWriter()).thenReturn(writer);
|
||||
when(request.getServletPath()).thenReturn(path);
|
||||
when(classLoader.getResources("locales/de/plugins.json")).thenReturn(resources);
|
||||
|
||||
servlet.doGet(request, response);
|
||||
|
||||
String json = Files.readLines(file, Charset.defaultCharset()).get(0);
|
||||
assertJson(json);
|
||||
verify(cache).get(path);
|
||||
verify(cache).put(eq(path), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void inProductionStageShouldGetFromCache() throws IOException {
|
||||
String path = "/locales/de/plugins.json";
|
||||
when(servlet.isProductionStage()).thenReturn(true);
|
||||
HttpServletRequest request = mock(HttpServletRequest.class);
|
||||
HttpServletResponse response = mock(HttpServletResponse.class);
|
||||
File file = temporaryFolder.newFile();
|
||||
PrintWriter writer = new PrintWriter(new FileOutputStream(file));
|
||||
when(response.getWriter()).thenReturn(writer);
|
||||
when(request.getServletPath()).thenReturn(path);
|
||||
when(classLoader.getResources("locales/de/plugins.json")).thenReturn(resources);
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
JsonNode node = objectMapper.readTree(GIT_PLUGIN_JSON);
|
||||
node = servlet.merge(node, objectMapper.readTree(HG_PLUGIN_JSON));
|
||||
node = servlet.merge(node, objectMapper.readTree(SVN_PLUGIN_JSON));
|
||||
when(cache.get(path)).thenReturn(node);
|
||||
|
||||
servlet.doGet(request, response);
|
||||
|
||||
String json = Files.readLines(file, Charset.defaultCharset()).get(0);
|
||||
verify(servlet, never()).collectJsonFile(path);
|
||||
verify(cache, never()).put(eq(path), any());
|
||||
verify(cache).get(path);
|
||||
assertJson(json);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void shouldCollectJsonFile() throws IOException {
|
||||
String path = "locales/de/plugins.json";
|
||||
when(classLoader.getResources(path)).thenReturn(resources);
|
||||
|
||||
Optional<JsonNode> jsonNodeOptional = servlet.collectJsonFile("/" + path);
|
||||
|
||||
assertJson(jsonNodeOptional.orElse(null));
|
||||
}
|
||||
|
||||
public void assertJson(JsonNode actual) throws IOException {
|
||||
assertJson(actual.toString());
|
||||
}
|
||||
|
||||
public void assertJson(String actual) throws IOException {
|
||||
assertThat(actual)
|
||||
.isNotEmpty()
|
||||
.contains(StringUtils.deleteWhitespace(GIT_PLUGIN_JSON.substring(1, GIT_PLUGIN_JSON.length() - 1)))
|
||||
.contains(StringUtils.deleteWhitespace(HG_PLUGIN_JSON.substring(1, HG_PLUGIN_JSON.length() - 1)))
|
||||
.contains(StringUtils.deleteWhitespace(SVN_PLUGIN_JSON.substring(1, SVN_PLUGIN_JSON.length() - 1)));
|
||||
}
|
||||
|
||||
public File createFileFromString(String json) throws IOException {
|
||||
File file = temporaryFolder.newFile();
|
||||
Files.write(json.getBytes(Charsets.UTF_8), file);
|
||||
return file;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user