Skip to content

Commit

Permalink
Merge pull request #384 from trellis-ldp/trellis-382
Browse files Browse the repository at this point in the history
Add a baseUrl parameter to the WebAcFilter class
  • Loading branch information
acoburn authored Apr 3, 2019
2 parents 624f2bf + 60aad58 commit 784138d
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,8 @@ public void run(final T config, final Environment environment) throws Exception
.ifPresent(challenges::add);
of(config.getAuth().getBasic()).filter(BasicAuthConfiguration::getEnabled).map(x -> "Basic")
.ifPresent(challenges::add);
environment.jersey().register(new WebAcFilter(webac, challenges, config.getAuth().getRealm()));
environment.jersey().register(new WebAcFilter(webac, challenges, config.getAuth().getRealm(),
config.getBaseUrl()));
});

// WebSub
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,11 @@ public TrellisWebDAVAuthzFilter(final AccessControlService accessService) {
* @param accessService the access service
* @param challengeTypes the WWW-Authenticate challenge types
* @param realm the authentication realm
* @param baseUrl the baseURL
*/
public TrellisWebDAVAuthzFilter(final AccessControlService accessService, final List<String> challengeTypes,
final String realm) {
super(accessService, challengeTypes, realm);
final String realm, final String baseUrl) {
super(accessService, challengeTypes, realm, baseUrl);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public void testFilterChallenges() throws Exception {
when(mockAccessControlService.getAccessModes(any(IRI.class), any(Session.class))).thenReturn(emptySet());

final TrellisWebDAVAuthzFilter filter = new TrellisWebDAVAuthzFilter(mockAccessControlService,
asList("Foo", "Bar"), "my-realm");
asList("Foo", "Bar"), "my-realm", null);

final List<Object> challenges = assertThrows(NotAuthorizedException.class, () -> filter.filter(mockContext),
"No auth exception thrown with no access modes!").getChallenges();
Expand Down
21 changes: 17 additions & 4 deletions core/http/src/main/java/org/trellisldp/http/WebAcFilter.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import static org.slf4j.LoggerFactory.getLogger;
import static org.trellisldp.api.TrellisUtils.TRELLIS_DATA_PREFIX;
import static org.trellisldp.api.TrellisUtils.getInstance;
import static org.trellisldp.http.core.HttpConstants.CONFIG_HTTP_BASE_URL;
import static org.trellisldp.http.core.HttpConstants.SESSION_PROPERTY;

import java.io.IOException;
Expand All @@ -41,6 +42,7 @@
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.ext.Provider;

import org.apache.commons.rdf.api.IRI;
Expand Down Expand Up @@ -83,6 +85,7 @@ public class WebAcFilter implements ContainerRequestFilter, ContainerResponseFil

protected final AccessControlService accessService;
private final List<String> challenges;
private final String baseUrl;

/**
* Create a new WebAc-based auth filter.
Expand All @@ -96,7 +99,8 @@ public WebAcFilter(final AccessControlService accessService) {

private WebAcFilter(final AccessControlService accessService, final Config config) {
this(accessService, asList(config.getOptionalValue(CONFIG_AUTH_CHALLENGES, String.class).orElse("").split(",")),
config.getOptionalValue(CONFIG_AUTH_REALM, String.class).orElse("trellis"));
config.getOptionalValue(CONFIG_AUTH_REALM, String.class).orElse("trellis"),
config.getOptionalValue(CONFIG_HTTP_BASE_URL, String.class).orElse(null));
}

/**
Expand All @@ -105,14 +109,16 @@ private WebAcFilter(final AccessControlService accessService, final Config confi
* @param accessService the access service
* @param challengeTypes the WWW-Authenticate challenge types
* @param realm the authentication realm
* @param baseUrl the base URL, may be null
*/
public WebAcFilter(final AccessControlService accessService, final List<String> challengeTypes,
final String realm) {
final String realm, final String baseUrl) {
requireNonNull(challengeTypes, "Challenges may not be null!");
requireNonNull(realm, "Realm may not be null!");
this.accessService = requireNonNull(accessService, "Access Control service may not be null!");
this.challenges = challengeTypes.stream().map(String::trim).map(ch -> ch + " realm=\"" + realm + "\"")
.collect(toList());
this.baseUrl = baseUrl;
}

@Override
Expand All @@ -139,11 +145,18 @@ public void filter(final ContainerRequestContext req, final ContainerResponseCon
if (SUCCESSFUL.equals(res.getStatusInfo().getFamily())
&& (!req.getUriInfo().getQueryParameters().containsKey(HttpConstants.EXT)
|| !req.getUriInfo().getQueryParameters().get(HttpConstants.EXT).contains(HttpConstants.ACL))) {
res.getHeaders().add(LINK, fromUri(req.getUriInfo().getAbsolutePathBuilder()
.queryParam(HttpConstants.EXT, HttpConstants.ACL).build()).rel(HttpConstants.ACL).build());
res.getHeaders().add(LINK, fromUri(getRequestUri(req).queryParam(HttpConstants.EXT, HttpConstants.ACL)
.build()).rel(HttpConstants.ACL).build());
}
}

private UriBuilder getRequestUri(final ContainerRequestContext req) {
if (nonNull(baseUrl)) {
return UriBuilder.fromUri(baseUrl).path(req.getUriInfo().getPath());
}
return req.getUriInfo().getAbsolutePathBuilder();
}

protected Session getOrCreateSession(final ContainerRequestContext ctx) {
final Object session = ctx.getProperty(SESSION_PROPERTY);
if (nonNull(session)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public Application configure() {
initMocks(this);

final WebAcFilter webacFilter = new WebAcFilter(mockAccessControlService, asList(BASIC_AUTH, DIGEST_AUTH),
"my-realm");
"my-realm", null);

final ResourceConfig config = new ResourceConfig();
config.register(new TrellisHttpResource(mockBundler));
Expand Down
49 changes: 48 additions & 1 deletion core/http/src/test/java/org/trellisldp/http/WebAcFilterTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
import static java.util.Collections.emptySet;
import static javax.ws.rs.core.Response.Status.OK;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
Expand All @@ -27,7 +28,11 @@

import javax.ws.rs.NotAuthorizedException;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.core.Link;
import javax.ws.rs.core.MultivaluedHashMap;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;

import org.apache.commons.rdf.api.IRI;
Expand Down Expand Up @@ -60,6 +65,9 @@ public class WebAcFilterTest {
@Mock
private ContainerRequestContext mockContext;

@Mock
private ContainerResponseContext mockResponseContext;

@Mock
private UriInfo mockUriInfo;

Expand Down Expand Up @@ -110,12 +118,51 @@ public void testFilterChallenges() throws Exception {
when(mockContext.getMethod()).thenReturn("POST");
when(mockAccessControlService.getAccessModes(any(IRI.class), any(Session.class))).thenReturn(emptySet());

final WebAcFilter filter = new WebAcFilter(mockAccessControlService, asList("Foo", "Bar"), "my-realm");
final WebAcFilter filter = new WebAcFilter(mockAccessControlService, asList("Foo", "Bar"), "my-realm",
"http://example.com/");

final List<Object> challenges = assertThrows(NotAuthorizedException.class, () -> filter.filter(mockContext),
"No auth exception thrown with no access modes!").getChallenges();

assertTrue(challenges.contains("Foo realm=\"my-realm\""), "Foo not among challenges!");
assertTrue(challenges.contains("Bar realm=\"my-realm\""), "Bar not among challenges!");
}

@Test
public void testFilterResponse() throws Exception {
final MultivaluedMap<String, Object> headers = new MultivaluedHashMap<>();
when(mockResponseContext.getStatusInfo()).thenReturn(OK);
when(mockResponseContext.getHeaders()).thenReturn(headers);
when(mockUriInfo.getAbsolutePathBuilder()).thenReturn(UriBuilder.fromUri("http://localhost/"));

final WebAcFilter filter = new WebAcFilter(mockAccessControlService, asList("Foo", "Bar"), "my-realm", null);

assertTrue(headers.isEmpty());
filter.filter(mockContext, mockResponseContext);
assertFalse(headers.isEmpty());

final Link link = (Link) headers.getFirst("Link");
assertNotNull(link);
assertEquals("acl", link.getRel());
assertEquals("http://localhost/?ext=acl", link.getUri().toString());
}

@Test
public void testFilterResponseBaseUrl() throws Exception {
final MultivaluedMap<String, Object> headers = new MultivaluedHashMap<>();
when(mockResponseContext.getStatusInfo()).thenReturn(OK);
when(mockResponseContext.getHeaders()).thenReturn(headers);

final WebAcFilter filter = new WebAcFilter(mockAccessControlService, asList("Foo", "Bar"), "my-realm",
"http://example.com/");

assertTrue(headers.isEmpty());
filter.filter(mockContext, mockResponseContext);
assertFalse(headers.isEmpty());

final Link link = (Link) headers.getFirst("Link");
assertNotNull(link);
assertEquals("acl", link.getRel());
assertEquals("http://example.com/?ext=acl", link.getUri().toString());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
package org.trellisldp.webapp;

import static java.util.Arrays.asList;
import static org.eclipse.microprofile.config.ConfigProvider.getConfig;
import static org.trellisldp.http.core.HttpConstants.CONFIG_HTTP_BASE_URL;

import org.glassfish.jersey.server.ResourceConfig;
import org.trellisldp.api.ServiceBundler;
Expand All @@ -39,8 +41,9 @@ public class TrellisApplication extends ResourceConfig {
public TrellisApplication() {
super();

final String baseUrl = getConfig().getOptionalValue(CONFIG_HTTP_BASE_URL, String.class).orElse(null);
final ServiceBundler serviceBundler = new WebappServiceBundler();
final TrellisHttpResource ldpResource = new TrellisHttpResource(serviceBundler);
final TrellisHttpResource ldpResource = new TrellisHttpResource(serviceBundler, baseUrl);
ldpResource.initialize();

register(ldpResource);
Expand All @@ -52,7 +55,7 @@ public TrellisApplication() {
register(new OAuthFilter());
register(new BasicAuthFilter());
register(new WebAcFilter(new WebACService(serviceBundler.getResourceService()), asList("Basic", "Bearer"),
"trellis"));
"trellis", baseUrl));

AppUtils.getCacheControlFilter().ifPresent(this::register);
AppUtils.getCORSFilter().ifPresent(this::register);
Expand Down

0 comments on commit 784138d

Please sign in to comment.