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