Skip to content

Commit

Permalink
allow injected sessions to be an existing transaction session, or get…
Browse files Browse the repository at this point in the history
… created within a workspace
  • Loading branch information
cbeer committed Jun 13, 2013
1 parent 1578d77 commit c0c122f
Show file tree
Hide file tree
Showing 6 changed files with 222 additions and 7 deletions.
Expand Up @@ -114,15 +114,27 @@ public void initialize() throws RepositoryException {
*/
public static final String toPath(final List<PathSegment> paths) {
final StringBuffer result = new StringBuffer();
LOGGER.trace("converting URI path to JCR path: {}", paths);

int i = 0;

for (final PathSegment path : paths) {
final String p = path.getPath();

if (!p.equals("")) {
if (p.equals("")) {
LOGGER.trace("Ignoring empty segment {}", p);
} else if (i == 0 && (p.startsWith("tx:") || p.startsWith("workspace:"))) {
LOGGER.trace("Ignoring internal segment {}", p);
i++;
} else {

LOGGER.trace("Adding segment {}", p);

if (!p.startsWith("[")) {
result.append('/');
}
result.append(p);
i++;
}
}

Expand Down
Expand Up @@ -46,7 +46,7 @@ public Session getValue() {
} else {
logger.debug("Returning unauthenticated Session.");
try {
return sessionFactory.getSession();
return sessionFactory.getSession(request);
} catch (final RepositoryException e) {
propagate(e);
}
Expand Down
Expand Up @@ -4,12 +4,15 @@
import static org.slf4j.LoggerFactory.getLogger;

import javax.annotation.PostConstruct;
import javax.jcr.PathNotFoundException;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.core.SecurityContext;

import org.fcrepo.Transaction;
import org.fcrepo.services.TransactionService;
import org.modeshape.jcr.api.ServletCredentials;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -22,6 +25,9 @@ public class SessionFactory {
@Autowired
private Repository repo;

@Autowired
private TransactionService transactionService;

public SessionFactory() {

}
Expand All @@ -47,6 +53,25 @@ public Session getSession(final String workspace)
return repo.login(workspace);
}

public Session getSession(final HttpServletRequest servletRequest)
throws RepositoryException {

final String workspace = getEmbeddedWorkspace(servletRequest);
final Transaction transaction = getEmbeddedTransaction(servletRequest);

final Session session;

if (transaction != null) {
session = transaction.getSession();
} else if (workspace != null) {
session = repo.login(workspace);
} else {
session = repo.login();
}

return session;
}

private static ServletCredentials getCredentials(
final SecurityContext securityContext,
final HttpServletRequest servletRequest) {
Expand All @@ -66,7 +91,27 @@ public Session getSession(final SecurityContext securityContext,
try {
final ServletCredentials creds =
getCredentials(securityContext, servletRequest);
return (creds != null) ? repo.login(creds) : repo.login();

final Transaction transaction = getEmbeddedTransaction(servletRequest);

final Session session;

if (transaction != null && creds != null) {
session = transaction.getSession().impersonate(creds);
} else if (creds != null) {

final String workspace = getEmbeddedWorkspace(servletRequest);

if (workspace != null) {
session = repo.login(creds, workspace);
} else {
session = repo.login(creds);
}
} else {
session = getSession(servletRequest);
}

return session;
} catch (final RepositoryException e) {
throw new IllegalStateException(e);
}
Expand All @@ -80,4 +125,31 @@ public AuthenticatedSessionProvider getSessionProvider(
getCredentials(securityContext, servletRequest);
return new AuthenticatedSessionProviderImpl(repo, creds);
}

private String getEmbeddedWorkspace(final HttpServletRequest servletRequest) {
final String requestPath = servletRequest.getPathInfo();
final String[] part = requestPath.split("/");

if (part.length > 1 && part[1].startsWith("workspace:")) {
return part[1].substring("workspace:".length());
} else {
return null;
}
}

private Transaction getEmbeddedTransaction(final HttpServletRequest servletRequest) throws PathNotFoundException {
final String requestPath = servletRequest.getPathInfo();
final String[] part = requestPath.split("/");

if (part.length > 1 && part[1].startsWith("tx:")) {
String txid = part[1].substring("tx:".length());
return transactionService.getTransaction(txid);
} else {
return null;
}
}

public void setTransactionService(final TransactionService transactionService) {
this.transactionService = transactionService;
}
}
Expand Up @@ -97,6 +97,61 @@ public void testToPath() {
assertEquals(expected, actual);
}

@Test
public void testToPathWorkspace() {
List<PathSegment> pathList = PathSegmentImpl.createPathList("workspace:abc", "bar", "baz");
// workspaces should be ignored
String expected = "/bar/baz";
String actual = AbstractResource.toPath(pathList);
assertEquals(expected, actual);
}


@Test
public void testToPathWorkspaceInSomeOtherSegment() {
List<PathSegment> pathList = PathSegmentImpl.createPathList("asdf", "workspace:abc", "bar", "baz");
// workspaces should be ignored
String expected = "/asdf/workspace:abc/bar/baz";
String actual = AbstractResource.toPath(pathList);
assertEquals(expected, actual);
}

@Test
public void testToPathWorkspaceWithEmptyPrefix() {
List<PathSegment> pathList = PathSegmentImpl.createPathList("", "workspace:abc", "bar", "baz");
// workspaces should be ignored
String expected = "/bar/baz";
String actual = AbstractResource.toPath(pathList);
assertEquals(expected, actual);
}

@Test
public void testToPathTransaction() {
List<PathSegment> pathList = PathSegmentImpl.createPathList("tx:abc", "bar", "baz");
// workspaces should be ignored
String expected = "/bar/baz";
String actual = AbstractResource.toPath(pathList);
assertEquals(expected, actual);
}

@Test
public void testToPathTxInSomeOtherSegment() {
List<PathSegment> pathList = PathSegmentImpl.createPathList("asdf", "tx:abc", "bar", "baz");
// workspaces should be ignored
String expected = "/asdf/tx:abc/bar/baz";
String actual = AbstractResource.toPath(pathList);
assertEquals(expected, actual);
}

@Test
public void testToPathTxWithEmptyPrefix() {
List<PathSegment> pathList = PathSegmentImpl.createPathList("", "tx:abc", "bar", "baz");
// workspaces should be ignored
String expected = "/bar/baz";
String actual = AbstractResource.toPath(pathList);
assertEquals(expected, actual);
}

@Test
public void testToPathUuid() {
List<PathSegment> pathList = PathSegmentImpl.createPathList("[foo]");
Expand Down
Expand Up @@ -24,14 +24,14 @@ public class InjectableSessionTest {

@Before
public void setUp() throws RepositoryException {
final HttpServletRequest mockHttpServletRequest =
mock(HttpServletRequest.class);
mockSession = mock(Session.class);
mockRepo = mock(Repository.class);
final SessionFactory mockSessionFactory = mock(SessionFactory.class);
mockSessionFactory.setRepository(mockRepo);
when(mockSessionFactory.getSession()).thenReturn(mockSession);
when(mockSessionFactory.getSession(mockHttpServletRequest)).thenReturn(mockSession);
final SecurityContext mockSecurityContext = mock(SecurityContext.class);
final HttpServletRequest mockHttpServletRequest =
mock(HttpServletRequest.class);
when(
mockSessionFactory.getSession(mockSecurityContext,
mockHttpServletRequest)).thenReturn(mockSession);
Expand Down
@@ -1,7 +1,9 @@

package org.fcrepo.session;

import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
Expand All @@ -12,9 +14,12 @@
import javax.jcr.LoginException;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.core.SecurityContext;

import org.fcrepo.Transaction;
import org.fcrepo.services.TransactionService;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
Expand Down Expand Up @@ -45,6 +50,7 @@ public void testGetSessionAuthenticated() throws LoginException,
final Principal mockUser = mock(Principal.class);
when(mockContext.getUserPrincipal()).thenReturn(mockUser);
final HttpServletRequest mockRequest = mock(HttpServletRequest.class);
when(mockRequest.getPathInfo()).thenReturn("/some/path");
testObj.getSession(mockContext, mockRequest);
verify(mockRepo).login(any(Credentials.class));
}
Expand All @@ -55,7 +61,77 @@ public void testGetSessionUnauthenticated() throws LoginException,
testObj.getSession();
verify(mockRepo).login();
}



@Test
public void testGetSessionWithWorkspace() throws LoginException,
RepositoryException {
final HttpServletRequest mockRequest = mock(HttpServletRequest.class);
when(mockRequest.getPathInfo()).thenReturn("/workspace:some-workspace/some/path");

testObj.getSession(mockRequest);
verify(mockRepo).login("some-workspace");
}


@Test
public void testGetSessionWithTransaction() throws LoginException,
RepositoryException {
final HttpServletRequest mockRequest = mock(HttpServletRequest.class);
when(mockRequest.getPathInfo()).thenReturn("/tx:123/some/path");

TransactionService mockTxService = mock(TransactionService.class);
testObj.setTransactionService(mockTxService);
Transaction mockTx = mock(Transaction.class);
when(mockTx.getSession()).thenReturn(mock(Session.class));
when(mockTxService.getTransaction("123")).thenReturn(mockTx);

final Session session = testObj.getSession(mockRequest);
assertEquals(mockTx.getSession(), session);
}


@Test
public void testGetAuthenticatedSessionWithWorkspace() throws LoginException,
RepositoryException {

final SecurityContext mockContext = mock(SecurityContext.class);
final Principal mockUser = mock(Principal.class);
when(mockContext.getUserPrincipal()).thenReturn(mockUser);

final HttpServletRequest mockRequest = mock(HttpServletRequest.class);
when(mockRequest.getPathInfo()).thenReturn("/workspace:some-workspace/some/path");

testObj.getSession(mockContext,mockRequest);
verify(mockRepo).login(any(Credentials.class), eq("some-workspace"));
}


@Test
public void testGetAuthenticatedSessionWithTransaction() throws LoginException,
RepositoryException {

final SecurityContext mockContext = mock(SecurityContext.class);
final Principal mockUser = mock(Principal.class);
when(mockContext.getUserPrincipal()).thenReturn(mockUser);

final HttpServletRequest mockRequest = mock(HttpServletRequest.class);
when(mockRequest.getPathInfo()).thenReturn("/tx:123/some/path");

TransactionService mockTxService = mock(TransactionService.class);
testObj.setTransactionService(mockTxService);
Transaction mockTx = mock(Transaction.class);
final Session txSession = mock(Session.class);
final Session mockSession = mock(Session.class);
when(txSession.impersonate(any(Credentials.class))).thenReturn(mockSession);
when(mockTx.getSession()).thenReturn(txSession);
when(mockTxService.getTransaction("123")).thenReturn(mockTx);

final Session session = testObj.getSession(mockContext,mockRequest);
assertEquals(mockSession, session);
verify(txSession).impersonate(any(Credentials.class));
}

@Test
public void testGetSessionProvider() {
final SecurityContext mockContext = mock(SecurityContext.class);
Expand Down

0 comments on commit c0c122f

Please sign in to comment.