001/*
002 * The contents of this file are subject to the license and copyright
003 * detailed in the LICENSE and NOTICE files at the root of the source
004 * tree.
005 */
006package org.fcrepo.auth.webac;
007
008import static org.apache.jena.riot.WebContent.contentTypeSPARQLUpdate;
009import static org.fcrepo.auth.common.ServletContainerAuthFilter.FEDORA_ADMIN_ROLE;
010import static org.fcrepo.auth.common.ServletContainerAuthFilter.FEDORA_USER_ROLE;
011import static org.fcrepo.auth.webac.URIConstants.WEBAC_MODE_APPEND;
012import static org.fcrepo.auth.webac.URIConstants.WEBAC_MODE_CONTROL;
013import static org.fcrepo.auth.webac.URIConstants.WEBAC_MODE_READ;
014import static org.fcrepo.auth.webac.URIConstants.WEBAC_MODE_WRITE;
015import static org.fcrepo.http.commons.session.TransactionConstants.ATOMIC_ID_HEADER;
016import static org.fcrepo.kernel.api.RdfLexicon.BASIC_CONTAINER;
017import static org.fcrepo.kernel.api.RdfLexicon.EMBED_CONTAINED;
018import static org.fcrepo.kernel.api.RdfLexicon.NON_RDF_SOURCE;
019import static org.fcrepo.kernel.api.RdfLexicon.REPOSITORY_NAMESPACE;
020import static org.junit.Assert.assertEquals;
021import static org.mockito.ArgumentMatchers.any;
022import static org.mockito.ArgumentMatchers.eq;
023import static org.mockito.Mockito.when;
024import static org.springframework.test.util.ReflectionTestUtils.setField;
025
026import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
027import static javax.servlet.http.HttpServletResponse.SC_OK;
028import static java.util.stream.Stream.of;
029
030import java.net.URI;
031import java.util.ArrayList;
032import java.util.Arrays;
033import java.util.List;
034
035import org.apache.shiro.SecurityUtils;
036import org.apache.shiro.mgt.SecurityManager;
037import org.apache.shiro.subject.Subject;
038import org.apache.shiro.subject.support.SubjectThreadState;
039import org.fcrepo.config.FedoraPropsConfig;
040import org.fcrepo.kernel.api.Transaction;
041import org.fcrepo.kernel.api.TransactionManager;
042import org.fcrepo.kernel.api.exception.PathNotFoundException;
043import org.fcrepo.kernel.api.identifiers.FedoraId;
044import org.fcrepo.kernel.api.models.Binary;
045import org.fcrepo.kernel.api.models.Container;
046import org.fcrepo.kernel.api.models.FedoraResource;
047import org.fcrepo.kernel.api.models.ResourceFactory;
048import org.junit.After;
049import org.junit.Before;
050import org.junit.Test;
051import org.junit.runner.RunWith;
052import org.mockito.InjectMocks;
053import org.mockito.Mock;
054import org.mockito.Mockito;
055import org.mockito.junit.MockitoJUnitRunner;
056import org.springframework.mock.web.MockFilterChain;
057import org.springframework.mock.web.MockHttpServletRequest;
058import org.springframework.mock.web.MockHttpServletResponse;
059
060/**
061 * @author peichman
062 */
063@RunWith(MockitoJUnitRunner.Silent.class)
064public class WebACFilterTest {
065
066    private static final String baseURL = "http://localhost";
067
068    private static final String transactionId = "abc-def";
069
070    private static final String transactionUri = baseURL + "/fcr:tx/" + transactionId;
071
072    private static final String testPath = "/testUri";
073
074    private static final String testChildPath = testPath + "/child";
075
076    private static final String testAclPath = testPath + "/fcr:acl";
077
078    private static final URI testURI = URI.create(baseURL + testPath);
079
080    private static final URI testAclURI = URI.create(baseURL + testAclPath);
081
082    private static final URI testChildURI = URI.create(baseURL + testChildPath);
083
084    private static final FedoraId testId = FedoraId.create(testPath);
085
086    private static final FedoraId testChildId = FedoraId.create(testChildPath);
087
088    @Mock
089    private SecurityManager mockSecurityManager;
090
091    @Mock
092    private TransactionManager mockTransactionManager;
093
094    @Mock
095    private ResourceFactory mockResourceFactory;
096
097    @Mock
098    private Transaction mockTransaction;
099
100    private FedoraResource mockContainer;
101
102    private FedoraResource mockChildContainer;
103
104    private FedoraResource mockBinary;
105
106    private FedoraResource mockRoot;
107
108    @InjectMocks
109    private final WebACFilter webacFilter = new WebACFilter();
110
111    private static final WebACPermission readPermission = new WebACPermission(WEBAC_MODE_READ, testURI);
112
113    private static final WebACPermission appendPermission = new WebACPermission(WEBAC_MODE_APPEND, testURI);
114
115    private static final WebACPermission writePermission = new WebACPermission(WEBAC_MODE_WRITE, testURI);
116
117    private static final WebACPermission controlPermission = new WebACPermission(WEBAC_MODE_CONTROL, testURI);
118
119    private static final WebACPermission readAclPermission = new WebACPermission(WEBAC_MODE_READ, testAclURI);
120    private static final WebACPermission appendAclPermission = new WebACPermission(WEBAC_MODE_APPEND, testAclURI);
121    private static final WebACPermission writeAclPermission = new WebACPermission(WEBAC_MODE_WRITE, testAclURI);
122    private static final WebACPermission controlAclPermission = new WebACPermission(WEBAC_MODE_CONTROL, testAclURI);
123
124    // We are dealing with internal IDs.
125    private static final WebACPermission readChildPermission = new WebACPermission(WEBAC_MODE_READ,
126            URI.create(testChildId.getFullId()));
127    private static final WebACPermission appendChildPermission = new WebACPermission(WEBAC_MODE_APPEND, testChildURI);
128    private static final WebACPermission writeChildPermission = new WebACPermission(WEBAC_MODE_WRITE, testChildURI);
129    private static final WebACPermission controlChildPermission = new WebACPermission(WEBAC_MODE_CONTROL, testChildURI);
130
131    private MockHttpServletRequest request;
132
133    private MockHttpServletResponse response;
134
135    private MockFilterChain filterChain;
136
137    private SubjectThreadState threadState;
138
139    private Subject mockSubject;
140
141    private FedoraPropsConfig propsConfig;
142
143    @Before
144    public void setupRequest() throws Exception {
145        propsConfig = new FedoraPropsConfig();
146        SecurityUtils.setSecurityManager(mockSecurityManager);
147
148        mockSubject = Mockito.mock(Subject.class);
149        threadState = new SubjectThreadState(mockSubject);
150        threadState.bind();
151
152        request = new MockHttpServletRequest();
153        response = new MockHttpServletResponse();
154        filterChain = new MockFilterChain();
155
156        // set default request URI and path info
157        // for the purposes of this test, there is no context path
158        // so the request URI and path info are the same
159        request.setPathInfo(testPath);
160        request.setRequestURI(testPath);
161        request.setContentType(null);
162        request.addHeader(ATOMIC_ID_HEADER, transactionUri);
163
164        setField(webacFilter, "transactionManager", mockTransactionManager);
165        setField(webacFilter, "fedoraPropsConfig", propsConfig);
166
167        mockContainer = Mockito.mock(Container.class);
168        mockChildContainer = Mockito.mock(Container.class);
169        mockBinary = Mockito.mock(Binary.class);
170        mockRoot = Mockito.mock(Container.class);
171
172        when(mockTransactionManager.get(transactionId)).thenReturn(mockTransaction);
173
174        when(mockResourceFactory.getResource(mockTransaction, testChildId))
175                .thenReturn(null);
176
177        when(mockResourceFactory.getResource(mockTransaction, FedoraId.getRepositoryRootId()))
178                .thenReturn(mockRoot);
179        when(mockContainer.getContainer()).thenReturn(mockRoot);
180        when(mockChildContainer.getContainer()).thenReturn(mockContainer);
181
182        when(mockContainer.getTypes()).thenReturn(Arrays.asList(URI.create(BASIC_CONTAINER.toString())));
183        when(mockContainer.getInteractionModel()).thenReturn(BASIC_CONTAINER.toString());
184        when(mockChildContainer.getTypes()).thenReturn(Arrays.asList(URI.create(BASIC_CONTAINER.toString())));
185        when(mockChildContainer.getInteractionModel()).thenReturn(BASIC_CONTAINER.toString());
186        when(mockBinary.getTypes()).thenReturn(Arrays.asList(URI.create(NON_RDF_SOURCE.toString())));
187        when(mockBinary.getInteractionModel()).thenReturn(NON_RDF_SOURCE.toString());
188
189        final List<URI> rootTypes = new ArrayList<>();
190        of("RepositoryRoot", "Resource", "Container").forEach(x -> rootTypes.add(URI.create(REPOSITORY_NAMESPACE +
191                x)));
192        when(mockRoot.getTypes()).thenReturn(rootTypes);
193        when(mockRoot.getInteractionModel()).thenReturn(BASIC_CONTAINER.toString());
194
195        // Setup Container by default
196        setupContainerResource();
197    }
198
199    private void setupContainerResource() throws Exception {
200        when(mockResourceFactory.getResource(mockTransaction, testId))
201                .thenReturn(mockContainer);
202        when(mockContainer.getFedoraId()). thenReturn(testId);
203        when(mockResourceFactory.getResource(mockTransaction, testChildId))
204                .thenReturn(mockChildContainer);
205        when(mockChildContainer.getFedoraId()).thenReturn(testChildId);
206    }
207
208    private void setupBinaryResource() throws Exception {
209        when(mockResourceFactory.getResource(mockTransaction, testId))
210                .thenReturn(mockBinary);
211        when(mockBinary.getFedoraId()).thenReturn(testId);
212    }
213
214    private void setupAdminUser() {
215        // admin user
216        when(mockSubject.isAuthenticated()).thenReturn(true);
217        when(mockSubject.hasRole(FEDORA_ADMIN_ROLE)).thenReturn(true);
218    }
219
220    private void setupAuthUserNoPerms() {
221        // authenticated user without permissions
222        when(mockSubject.isAuthenticated()).thenReturn(true);
223        when(mockSubject.hasRole(FEDORA_ADMIN_ROLE)).thenReturn(false);
224        when(mockSubject.hasRole(FEDORA_USER_ROLE)).thenReturn(true);
225        when(mockSubject.isPermitted(readPermission)).thenReturn(false);
226        when(mockSubject.isPermitted(appendPermission)).thenReturn(false);
227        when(mockSubject.isPermitted(writePermission)).thenReturn(false);
228        when(mockSubject.isPermitted(controlPermission)).thenReturn(false);
229
230    }
231
232    private void setupAuthUserReadOnly() {
233        // authenticated user with only read permissions
234        when(mockSubject.isAuthenticated()).thenReturn(true);
235        when(mockSubject.hasRole(FEDORA_ADMIN_ROLE)).thenReturn(false);
236        when(mockSubject.hasRole(FEDORA_USER_ROLE)).thenReturn(true);
237        when(mockSubject.isPermitted(readPermission)).thenReturn(true);
238        when(mockSubject.isPermitted(appendPermission)).thenReturn(false);
239        when(mockSubject.isPermitted(writePermission)).thenReturn(false);
240        when(mockSubject.isPermitted(controlPermission)).thenReturn(false);
241
242    }
243
244    private void setupAuthUserAppendOnly() {
245        // authenticated user with only read permissions
246        when(mockSubject.isAuthenticated()).thenReturn(true);
247        when(mockSubject.hasRole(FEDORA_ADMIN_ROLE)).thenReturn(false);
248        when(mockSubject.hasRole(FEDORA_USER_ROLE)).thenReturn(true);
249        when(mockSubject.isPermitted(readPermission)).thenReturn(false);
250        when(mockSubject.isPermitted(appendPermission)).thenReturn(true);
251        when(mockSubject.isPermitted(appendChildPermission)).thenReturn(true);
252        when(mockSubject.isPermitted(writePermission)).thenReturn(false);
253        when(mockSubject.isPermitted(controlPermission)).thenReturn(false);
254
255    }
256
257    private void setupAuthUserReadAppend() {
258        // authenticated user with only read permissions
259        when(mockSubject.isAuthenticated()).thenReturn(true);
260        when(mockSubject.hasRole(FEDORA_ADMIN_ROLE)).thenReturn(false);
261        when(mockSubject.hasRole(FEDORA_USER_ROLE)).thenReturn(true);
262        when(mockSubject.isPermitted(readPermission)).thenReturn(true);
263        when(mockSubject.isPermitted(appendPermission)).thenReturn(true);
264        when(mockSubject.isPermitted(appendChildPermission)).thenReturn(true);
265        when(mockSubject.isPermitted(writePermission)).thenReturn(false);
266        when(mockSubject.isPermitted(controlPermission)).thenReturn(false);
267    }
268
269    private void setupAuthUserReadWrite() {
270        // authenticated user with read and write permissions
271        when(mockSubject.isAuthenticated()).thenReturn(true);
272        when(mockSubject.hasRole(FEDORA_ADMIN_ROLE)).thenReturn(false);
273        when(mockSubject.hasRole(FEDORA_USER_ROLE)).thenReturn(true);
274        when(mockSubject.isPermitted(readPermission)).thenReturn(true);
275        when(mockSubject.isPermitted(appendPermission)).thenReturn(false);
276        when(mockSubject.isPermitted(writePermission)).thenReturn(true);
277        when(mockSubject.isPermitted(controlPermission)).thenReturn(false);
278    }
279
280    private void setupAuthUserAclControl() {
281        // authenticated user with read and write permissions
282        when(mockSubject.isAuthenticated()).thenReturn(true);
283        when(mockSubject.hasRole(FEDORA_ADMIN_ROLE)).thenReturn(false);
284        when(mockSubject.hasRole(FEDORA_USER_ROLE)).thenReturn(true);
285        when(mockSubject.isPermitted(readAclPermission)).thenReturn(false);
286        when(mockSubject.isPermitted(appendAclPermission)).thenReturn(false);
287        when(mockSubject.isPermitted(writeAclPermission)).thenReturn(false);
288        when(mockSubject.isPermitted(controlAclPermission)).thenReturn(true);
289    }
290
291    private void setupAuthUserNoAclControl() {
292        // authenticated user with read and write permissions
293        when(mockSubject.isAuthenticated()).thenReturn(true);
294        when(mockSubject.hasRole(FEDORA_ADMIN_ROLE)).thenReturn(false);
295        when(mockSubject.hasRole(FEDORA_USER_ROLE)).thenReturn(true);
296        when(mockSubject.isPermitted(readAclPermission)).thenReturn(true);
297        when(mockSubject.isPermitted(appendAclPermission)).thenReturn(true);
298        when(mockSubject.isPermitted(writeAclPermission)).thenReturn(true);
299        when(mockSubject.isPermitted(controlAclPermission)).thenReturn(false);
300    }
301
302    private void setupAuthUserReadAppendWrite() {
303        // authenticated user with read and write permissions
304        when(mockSubject.isAuthenticated()).thenReturn(true);
305        when(mockSubject.hasRole(FEDORA_ADMIN_ROLE)).thenReturn(false);
306        when(mockSubject.hasRole(FEDORA_USER_ROLE)).thenReturn(true);
307        when(mockSubject.isPermitted(readPermission)).thenReturn(true);
308        when(mockSubject.isPermitted(appendPermission)).thenReturn(true);
309        when(mockSubject.isPermitted(appendChildPermission)).thenReturn(true);
310        when(mockSubject.isPermitted(writePermission)).thenReturn(true);
311        when(mockSubject.isPermitted(controlPermission)).thenReturn(true);
312
313    }
314
315    private void setupAuthUserReadParentAndChildren(final boolean accessToChild) {
316        // authenticated user has read to a container and it's contained resources.
317        when(mockSubject.isAuthenticated()).thenReturn(true);
318        when(mockSubject.hasRole(FEDORA_ADMIN_ROLE)).thenReturn(false);
319        when(mockSubject.hasRole(FEDORA_USER_ROLE)).thenReturn(true);
320        when(mockSubject.isPermitted(readPermission)).thenReturn(true);
321        when(mockSubject.isPermitted(appendPermission)).thenReturn(false);
322        when(mockSubject.isPermitted(writePermission)).thenReturn(false);
323        when(mockSubject.isPermitted(controlPermission)).thenReturn(false);
324        when(mockSubject.isPermitted(readChildPermission)).thenReturn(accessToChild);
325        when(mockSubject.isPermitted(appendChildPermission)).thenReturn(false);
326        when(mockSubject.isPermitted(writeChildPermission)).thenReturn(false);
327        when(mockSubject.isPermitted(controlChildPermission)).thenReturn(false);
328        when(mockResourceFactory.getChildren(any(), eq(testId))).thenReturn(List.of(mockChildContainer).stream());
329    }
330
331    private void setupEmbeddedResourceHeader() {
332        request.addHeader("Prefer", "return=representation; include=\"" + EMBED_CONTAINED + "\"");
333    }
334
335    @Test
336    public void testAdminUserHead() throws Exception {
337        setupAdminUser();
338        // HEAD => 200
339        request.setMethod("HEAD");
340        webacFilter.doFilter(request, response, filterChain);
341        assertEquals(SC_OK, response.getStatus());
342    }
343
344    @Test
345    public void testAdminUserOptions() throws Exception {
346        setupAdminUser();
347        // GET => 200
348        request.setMethod("OPTIONS");
349        webacFilter.doFilter(request, response, filterChain);
350        assertEquals(SC_OK, response.getStatus());
351    }
352
353    @Test
354    public void testAdminUserGet() throws Exception {
355        setupAdminUser();
356        // GET => 200
357        request.setMethod("GET");
358        webacFilter.doFilter(request, response, filterChain);
359        assertEquals(SC_OK, response.getStatus());
360    }
361
362    @Test
363    public void testAdminUserPost() throws Exception {
364        setupAdminUser();
365        // GET => 200
366        request.setMethod("POST");
367        webacFilter.doFilter(request, response, filterChain);
368        assertEquals(SC_OK, response.getStatus());
369    }
370
371    @Test
372    public void testAdminUserPut() throws Exception {
373        setupAdminUser();
374        // GET => 200
375        request.setMethod("PUT");
376        webacFilter.doFilter(request, response, filterChain);
377        assertEquals(SC_OK, response.getStatus());
378    }
379
380    @Test
381    public void testAdminUserPatch() throws Exception {
382        setupAdminUser();
383        // GET => 200
384        request.setMethod("PATCH");
385        webacFilter.doFilter(request, response, filterChain);
386        assertEquals(SC_OK, response.getStatus());
387    }
388
389    @Test
390    public void testAdminUserDelete() throws Exception {
391        setupAdminUser();
392        // GET => 200
393        request.setMethod("DELETE");
394        webacFilter.doFilter(request, response, filterChain);
395        assertEquals(SC_OK, response.getStatus());
396    }
397
398    @Test
399    public void testAuthUserNoPermsHead() throws Exception {
400        setupAuthUserNoPerms();
401        // HEAD => 403
402        request.setMethod("HEAD");
403        webacFilter.doFilter(request, response, filterChain);
404        assertEquals(SC_FORBIDDEN, response.getStatus());
405    }
406
407    @Test
408    public void testAuthUserNoPermsOptions() throws Exception {
409        setupAuthUserNoPerms();
410        // GET => 403
411        request.setMethod("OPTIONS");
412        webacFilter.doFilter(request, response, filterChain);
413        assertEquals(SC_FORBIDDEN, response.getStatus());
414    }
415
416    @Test
417    public void testAuthUserNoPermsGet() throws Exception {
418        setupAuthUserNoPerms();
419        // GET => 403
420        request.setMethod("GET");
421        webacFilter.doFilter(request, response, filterChain);
422        assertEquals(SC_FORBIDDEN, response.getStatus());
423    }
424
425    @Test
426    public void testAuthUserNoPermsPost() throws Exception {
427        setupAuthUserNoPerms();
428        // POST => 403
429        request.setMethod("POST");
430        webacFilter.doFilter(request, response, filterChain);
431        assertEquals(SC_FORBIDDEN, response.getStatus());
432    }
433
434    @Test
435    public void testAuthUserNoPermsPut() throws Exception {
436        setupAuthUserNoPerms();
437        // PUT => 403
438        request.setMethod("PUT");
439        webacFilter.doFilter(request, response, filterChain);
440        assertEquals(SC_FORBIDDEN, response.getStatus());
441    }
442
443    @Test
444    public void testAuthUserNoPermsPatch() throws Exception {
445        setupAuthUserNoPerms();
446        // PATCH => 403
447        request.setMethod("PATCH");
448        webacFilter.doFilter(request, response, filterChain);
449        assertEquals(SC_FORBIDDEN, response.getStatus());
450    }
451
452    @Test
453    public void testAuthUserNoPermsDelete() throws Exception {
454        setupAuthUserNoPerms();
455        // DELETE => 403
456        request.setMethod("DELETE");
457        webacFilter.doFilter(request, response, filterChain);
458        assertEquals(SC_FORBIDDEN, response.getStatus());
459    }
460
461    @Test
462    public void testAuthUserReadOnlyHead() throws Exception {
463        setupAuthUserReadOnly();
464        // HEAD => 200
465        request.setMethod("HEAD");
466        webacFilter.doFilter(request, response, filterChain);
467        assertEquals(SC_OK, response.getStatus());
468    }
469
470    @Test
471    public void testAuthUserReadOnlyOptions() throws Exception {
472        setupAuthUserReadOnly();
473        // GET => 200
474        request.setMethod("OPTIONS");
475        webacFilter.doFilter(request, response, filterChain);
476        assertEquals(SC_OK, response.getStatus());
477    }
478
479    @Test
480    public void testAuthUserReadOnlyGet() throws Exception {
481        setupAuthUserReadOnly();
482        // GET => 200
483        request.setMethod("GET");
484        webacFilter.doFilter(request, response, filterChain);
485        assertEquals(SC_OK, response.getStatus());
486    }
487
488    @Test
489    public void testAuthUserReadOnlyPost() throws Exception {
490        setupAuthUserReadOnly();
491        // POST => 403
492        request.setMethod("POST");
493        webacFilter.doFilter(request, response, filterChain);
494        assertEquals(SC_FORBIDDEN, response.getStatus());
495    }
496
497    @Test
498    public void testAuthUserReadOnlyPut() throws Exception {
499        setupAuthUserReadOnly();
500        // PUT => 403
501        request.setMethod("PUT");
502        request.setRequestURI(testPath);
503        webacFilter.doFilter(request, response, filterChain);
504        assertEquals(SC_FORBIDDEN, response.getStatus());
505    }
506
507    @Test
508    public void testAuthUserReadOnlyPatch() throws Exception {
509        setupAuthUserReadOnly();
510        // PATCH => 403
511        request.setMethod("PATCH");
512        webacFilter.doFilter(request, response, filterChain);
513        assertEquals(SC_FORBIDDEN, response.getStatus());
514    }
515
516    @Test
517    public void testAuthUserReadOnlyDelete() throws Exception {
518        setupAuthUserReadOnly();
519        // DELETE => 403
520        request.setMethod("DELETE");
521        webacFilter.doFilter(request, response, filterChain);
522        assertEquals(SC_FORBIDDEN, response.getStatus());
523    }
524
525    @Test
526    public void testAuthUserReadAppendPatchNonSparqlContent() throws Exception {
527        setupAuthUserReadAppend();
528        // PATCH (Non Sparql Content) => 403
529        request.setRequestURI(testPath);
530        request.setMethod("PATCH");
531        webacFilter.doFilter(request, response, filterChain);
532        assertEquals(SC_FORBIDDEN, response.getStatus());
533    }
534
535    @Test
536    public void testAuthUserReadAppendPatchSparqlNoContent() throws Exception {
537        setupAuthUserReadAppend();
538        // PATCH (Sparql No Content) => 200 (204)
539        request.setContentType(contentTypeSPARQLUpdate);
540        request.setRequestURI(testPath);
541        request.setMethod("PATCH");
542        webacFilter.doFilter(request, response, filterChain);
543        assertEquals(SC_OK, response.getStatus());
544    }
545
546    @Test
547    public void testAuthUserReadAppendPatchSparqlInvalidContent() throws Exception {
548        setupAuthUserReadAppend();
549        // PATCH (Sparql Invalid Content) => 403
550        request.setContentType(contentTypeSPARQLUpdate);
551        request.setContent("SOME TEXT".getBytes());
552        request.setRequestURI(testPath);
553        request.setMethod("PATCH");
554        webacFilter.doFilter(request, response, filterChain);
555        assertEquals(SC_FORBIDDEN, response.getStatus());
556    }
557
558    @Test
559    public void testAuthUserReadAppendPatchSparqlInsert() throws Exception {
560        setupAuthUserReadAppend();
561        // PATCH (Sparql INSERT) => 200 (204)
562        final String updateString =
563                "INSERT { <> <http://purl.org/dc/elements/1.1/title> \"new title\" } WHERE { }";
564        request.setContentType(contentTypeSPARQLUpdate);
565        request.setContent(updateString.getBytes());
566        request.setRequestURI(testPath);
567        request.setMethod("PATCH");
568        webacFilter.doFilter(request, response, filterChain);
569        assertEquals(SC_OK, response.getStatus());
570    }
571
572    @Test
573    public void testAuthUserReadAppendPatchSparqlDelete() throws Exception {
574        setupAuthUserReadAppend();
575        // PATCH (Sparql DELETE) => 403
576        final String updateString =
577                "DELETE { <> <http://purl.org/dc/elements/1.1/title> \"new title\" } WHERE { }";
578        request.setContentType(contentTypeSPARQLUpdate);
579        request.setContent(updateString.getBytes());
580        request.setRequestURI(testPath);
581        request.setMethod("PATCH");
582        webacFilter.doFilter(request, response, filterChain);
583        assertEquals(SC_FORBIDDEN, response.getStatus());
584    }
585
586    @Test
587    public void testAuthUserAppendPostContainer() throws Exception {
588        setupAuthUserAppendOnly();
589        // POST => 200
590        request.setRequestURI(testPath);
591        request.setMethod("POST");
592        webacFilter.doFilter(request, response, filterChain);
593        assertEquals(SC_OK, response.getStatus());
594    }
595
596    @Test
597    public void testAuthUserAppendPostBinary() throws Exception {
598        setupAuthUserAppendOnly();
599        setupBinaryResource();
600        // POST => 403
601        request.setRequestURI(testPath);
602        request.setMethod("POST");
603        webacFilter.doFilter(request, response, filterChain);
604        assertEquals(SC_FORBIDDEN, response.getStatus());
605    }
606
607    @Test
608    public void testAuthUserAppendDelete() throws Exception {
609        setupAuthUserAppendOnly();
610        // POST => 403
611        request.setRequestURI(testPath);
612        request.setMethod("DELETE");
613        webacFilter.doFilter(request, response, filterChain);
614        assertEquals(SC_FORBIDDEN, response.getStatus());
615    }
616
617    @Test
618    public void testAuthUserReadAppendPostContainer() throws Exception {
619        setupAuthUserReadAppend();
620        // POST => 200
621        request.setRequestURI(testPath);
622        request.setMethod("POST");
623        webacFilter.doFilter(request, response, filterChain);
624        assertEquals(SC_OK, response.getStatus());
625    }
626
627    @Test
628    public void testAuthUserReadAppendPostBinary() throws Exception {
629        setupAuthUserReadAppend();
630        setupBinaryResource();
631        // POST => 403
632        request.setRequestURI(testPath);
633        request.setMethod("POST");
634        webacFilter.doFilter(request, response, filterChain);
635        assertEquals(SC_FORBIDDEN, response.getStatus());
636    }
637
638    @Test
639    public void testAuthUserReadAppendDelete() throws Exception {
640        setupAuthUserReadAppend();
641        // DELETE => 403
642        request.setRequestURI(testPath);
643        request.setMethod("DELETE");
644        webacFilter.doFilter(request, response, filterChain);
645        assertEquals(SC_FORBIDDEN, response.getStatus());
646    }
647
648    @Test
649    public void testAuthUserReadAppendWritePostContainer() throws Exception {
650        setupAuthUserReadAppendWrite();
651        // POST => 200
652        request.setRequestURI(testPath);
653        request.setMethod("POST");
654        webacFilter.doFilter(request, response, filterChain);
655        assertEquals(SC_OK, response.getStatus());
656    }
657
658    @Test
659    public void testAuthUserReadAppendWritePostBinary() throws Exception {
660        setupAuthUserReadAppendWrite();
661        setupBinaryResource();
662        // POST => 200
663        request.setRequestURI(testPath);
664        request.setMethod("POST");
665        webacFilter.doFilter(request, response, filterChain);
666        assertEquals(SC_OK, response.getStatus());
667    }
668
669    @Test
670    public void testAuthUserReadWriteHead() throws Exception {
671        setupAuthUserReadWrite();
672        // HEAD => 200
673        request.setMethod("HEAD");
674        webacFilter.doFilter(request, response, filterChain);
675        assertEquals(SC_OK, response.getStatus());
676    }
677
678    @Test
679    public void testAuthUserReadWriteOptions() throws Exception {
680        setupAuthUserReadWrite();
681        // GET => 200
682        request.setMethod("OPTIONS");
683        webacFilter.doFilter(request, response, filterChain);
684        assertEquals(SC_OK, response.getStatus());
685    }
686
687    @Test
688    public void testAuthUserReadWriteGet() throws Exception {
689        setupAuthUserReadWrite();
690        // GET => 200
691        request.setMethod("GET");
692        webacFilter.doFilter(request, response, filterChain);
693        assertEquals(SC_OK, response.getStatus());
694    }
695
696    @Test
697    public void testAuthUserReadWritePost() throws Exception {
698        setupAuthUserReadWrite();
699        // POST => 200
700        request.setMethod("POST");
701        webacFilter.doFilter(request, response, filterChain);
702        assertEquals(SC_OK, response.getStatus());
703    }
704
705    @Test
706    public void testAuthUserReadWritePut() throws Exception {
707        setupAuthUserReadWrite();
708        // PUT => 200
709        request.setMethod("PUT");
710        request.setRequestURI(testPath);
711        webacFilter.doFilter(request, response, filterChain);
712        assertEquals(SC_OK, response.getStatus());
713    }
714
715    @Test
716    public void testAuthUserReadWritePatch() throws Exception {
717        setupAuthUserReadWrite();
718        // PATCH => 200
719        request.setMethod("PATCH");
720        webacFilter.doFilter(request, response, filterChain);
721        assertEquals(SC_OK, response.getStatus());
722    }
723
724    @Test
725    public void testAuthUserReadWriteDelete() throws Exception {
726        setupAuthUserReadWrite();
727        // DELETE => 200
728        request.setMethod("DELETE");
729        webacFilter.doFilter(request, response, filterChain);
730        assertEquals(SC_OK, response.getStatus());
731    }
732
733    @Test
734    public void testAuthUserReadAppendWriteDelete() throws Exception {
735        setupAuthUserReadAppendWrite();
736        // DELETE => 200
737        request.setRequestURI(testPath);
738        request.setMethod("DELETE");
739        webacFilter.doFilter(request, response, filterChain);
740        assertEquals(SC_OK, response.getStatus());
741    }
742
743    @Test
744    public void testAuthUserAppendPutNewChild() throws Exception {
745        setupAuthUserAppendOnly();
746        // PUT => 200
747        when(mockResourceFactory.getResource((Transaction)any(), eq(testChildId)))
748                .thenThrow(PathNotFoundException.class);
749        request.setRequestURI(testChildPath);
750        request.setPathInfo(testChildPath);
751        request.setMethod("PUT");
752        webacFilter.doFilter(request, response, filterChain);
753        assertEquals(SC_OK, response.getStatus());
754    }
755
756    @Test
757    public void testAclControlPutToAcl() throws Exception {
758        setupAuthUserAclControl();
759        request.setRequestURI(testAclPath);
760        request.setMethod("PUT");
761        webacFilter.doFilter(request, response, filterChain);
762        assertEquals(SC_OK, response.getStatus());
763    }
764
765    @Test
766    public void testNoAclControlPutToAcl() throws Exception {
767        setupAuthUserNoAclControl();
768        request.setRequestURI(testAclPath);
769        request.setMethod("PUT");
770        webacFilter.doFilter(request, response, filterChain);
771        assertEquals(SC_FORBIDDEN, response.getStatus());
772    }
773
774    @Test
775    public void testAclControlGetToAcl() throws Exception {
776        setupAuthUserAclControl();
777        request.setRequestURI(testAclPath);
778        request.setMethod("GET");
779        webacFilter.doFilter(request, response, filterChain);
780        assertEquals(SC_OK, response.getStatus());
781    }
782
783    @Test
784    public void testNoAclControlGetToAcl() throws Exception {
785        setupAuthUserNoAclControl();
786        request.setRequestURI(testAclPath);
787        request.setMethod("GET");
788        webacFilter.doFilter(request, response, filterChain);
789        assertEquals(SC_FORBIDDEN, response.getStatus());
790    }
791
792    @Test
793    public void testAclControlHeadToAcl() throws Exception {
794        setupAuthUserAclControl();
795        request.setRequestURI(testAclPath);
796        request.setMethod("HEAD");
797        webacFilter.doFilter(request, response, filterChain);
798        assertEquals(SC_OK, response.getStatus());
799    }
800
801    @Test
802    public void testNoAclControlHeadToAcl() throws Exception {
803        setupAuthUserNoAclControl();
804        request.setRequestURI(testAclPath);
805        request.setMethod("HEAD");
806        webacFilter.doFilter(request, response, filterChain);
807        assertEquals(SC_FORBIDDEN, response.getStatus());
808    }
809
810    @Test
811    public void testAclControlPatchToAcl() throws Exception {
812        setupAuthUserAclControl();
813        request.setRequestURI(testAclPath);
814        request.setMethod("PATCH");
815        webacFilter.doFilter(request, response, filterChain);
816        assertEquals(SC_OK, response.getStatus());
817    }
818
819    @Test
820    public void testNoAclControlPatchToAcl() throws Exception {
821        setupAuthUserNoAclControl();
822        request.setRequestURI(testAclPath);
823        request.setMethod("PATCH");
824        webacFilter.doFilter(request, response, filterChain);
825        assertEquals(SC_FORBIDDEN, response.getStatus());
826    }
827
828    @Test
829    public void testAclControlDelete() throws Exception {
830        setupAuthUserAclControl();
831        request.setRequestURI(testAclPath);
832        request.setMethod("DELETE");
833        webacFilter.doFilter(request, response, filterChain);
834        assertEquals(SC_OK, response.getStatus());
835    }
836
837    @Test
838    public void testNoAclControlDelete() throws Exception {
839        setupAuthUserNoAclControl();
840        request.setRequestURI(testAclPath);
841        request.setMethod("DELETE");
842        webacFilter.doFilter(request, response, filterChain);
843        assertEquals(SC_FORBIDDEN, response.getStatus());
844    }
845
846    @Test
847    public void testAclReadEmbeddedOk() throws Exception {
848        setupAuthUserReadParentAndChildren(true);
849        setupEmbeddedResourceHeader();
850        request.setRequestURI(testPath);
851        request.setMethod("GET");
852        webacFilter.doFilter(request, response, filterChain);
853        assertEquals(SC_OK, response.getStatus());
854    }
855
856    @Test
857    public void testAclReadEmbeddedDenied() throws Exception {
858        setupAuthUserReadParentAndChildren(false);
859        setupEmbeddedResourceHeader();
860        request.setRequestURI(testPath);
861        request.setMethod("GET");
862        webacFilter.doFilter(request, response, filterChain);
863        assertEquals(SC_FORBIDDEN, response.getStatus());
864    }
865
866    @After
867    public void clearSubject() {
868        // unbind the subject to the thread
869        threadState.restore();
870    }
871}