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.Collections.singletonList;
021import static org.apache.jena.graph.NodeFactory.createURI;
022import static org.apache.jena.rdf.model.ModelFactory.createDefaultModel;
023import static org.apache.jena.riot.Lang.TTL;
024import static org.fcrepo.auth.webac.URIConstants.FOAF_AGENT_VALUE;
025import static org.fcrepo.auth.webac.URIConstants.VCARD_GROUP;
026import static org.fcrepo.auth.webac.URIConstants.WEBAC_MODE_READ_VALUE;
027import static org.fcrepo.auth.webac.URIConstants.WEBAC_MODE_WRITE_VALUE;
028import static org.fcrepo.http.api.FedoraAcl.ROOT_AUTHORIZATION_PROPERTY;
029import static org.fcrepo.kernel.api.FedoraTypes.FEDORA_ID_PREFIX;
030import static org.fcrepo.kernel.api.RdfLexicon.FEDORA_RESOURCE;
031import org.fcrepo.kernel.api.exception.PathNotFoundException;
032import org.fcrepo.kernel.api.identifiers.FedoraId;
033import org.fcrepo.kernel.api.models.ResourceFactory;
034import static org.junit.Assert.assertEquals;
035import static org.junit.Assert.assertNull;
036import static org.junit.Assert.assertTrue;
037import static org.mockito.Mockito.when;
038import static org.springframework.test.util.ReflectionTestUtils.setField;
039
040import java.net.URI;
041import java.util.ArrayList;
042import java.util.Collection;
043import java.util.List;
044import java.util.Map;
045
046import org.apache.jena.graph.Triple;
047import org.apache.jena.rdf.model.Model;
048import org.apache.jena.riot.Lang;
049import org.apache.jena.riot.RDFDataMgr;
050import org.fcrepo.kernel.api.Transaction;
051import org.fcrepo.kernel.api.RdfStream;
052import org.fcrepo.kernel.api.exception.RepositoryException;
053import org.fcrepo.kernel.api.models.FedoraResource;
054import org.fcrepo.kernel.api.rdf.DefaultRdfStream;
055import org.junit.Before;
056import org.junit.Ignore;
057import org.junit.Rule;
058import org.junit.Test;
059import org.junit.contrib.java.lang.system.RestoreSystemProperties;
060import org.junit.runner.RunWith;
061import org.mockito.Mock;
062import org.mockito.junit.MockitoJUnitRunner;
063
064/**
065 * @author acoburn
066 * @since 9/3/15
067 */
068@RunWith(MockitoJUnitRunner.Silent.class)
069public class WebACRolesProviderTest {
070
071    private WebACRolesProvider roleProvider;
072
073    private static final String FEDORA_PREFIX = "info:fedora";
074    private static final String FEDORA_URI_PREFIX = "file:///rest";
075    private static final URI FEDORA_RESOURCE_URI = URI.create(FEDORA_RESOURCE.getURI());
076
077    @Mock
078    private Transaction mockTransaction;
079
080    @Mock
081    private ResourceFactory mockResourceFactory;
082
083    @Mock
084    private FedoraResource mockResource, mockParentResource;
085
086    @Mock
087    private FedoraResource mockAclResource;
088
089    @Mock
090    private FedoraResource mockAgentClassResource;
091
092    @Rule
093    public final RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties();
094
095    @Before
096    public void setUp() throws RepositoryException {
097
098        roleProvider = new WebACRolesProvider();
099        setField(roleProvider, "resourceFactory", mockResourceFactory);
100
101        when(mockResource.getDescribedResource()).thenReturn(mockResource);
102        when(mockResource.getDescription()).thenReturn(mockResource);
103
104        when(mockResource.getOriginalResource()).thenReturn(mockResource);
105    }
106
107    private void assertOnlyDefaultAgentInRoles(final Map<String, Collection<String>> roles) {
108        assertEquals(1, roles.size());
109        assertTrue(roles.keySet().contains(FOAF_AGENT_VALUE));
110    }
111
112    @Test
113    public void noAclTest() throws RepositoryException {
114        final String accessTo = "/dark/archive/sunshine";
115
116        when(mockResource.getAcl()).thenReturn(null);
117        when(mockParentResource.getAcl()).thenReturn(null);
118
119        when(mockResource.getId()).thenReturn(accessTo);
120        when(mockResource.getContainer()).thenReturn(mockParentResource);
121        when(mockResource.getTriples())
122                .thenReturn(new DefaultRdfStream(createURI("subject")));
123        when(mockResource.getOriginalResource()).thenReturn(mockResource);
124
125        when(mockParentResource.getOriginalResource()).thenReturn(mockParentResource);
126        when(mockParentResource.getId()).thenReturn(null);
127
128        final Map<String, Collection<String>> roles = roleProvider.getRoles(mockResource, mockTransaction);
129
130        assertOnlyDefaultAgentInRoles(roles);
131    }
132
133    @Ignore // TODO FIX THIS TEST
134    @Test
135    public void acl01ParentTest() throws RepositoryException {
136        final String agent = "user01";
137        final String parentPath = "/webacl_box1";
138        final String accessTo = parentPath + "/foo";
139        final String acl = "/acls/01/acl.ttl";
140
141        when(mockResource.getAcl()).thenReturn(null);
142        when(mockParentResource.getAcl()).thenReturn(mockAclResource);
143
144        when(mockResource.getId()).thenReturn(addPrefix(accessTo));
145        when(mockResource.getContainer()).thenReturn(mockParentResource);
146        when(mockResource.getOriginalResource()).thenReturn(mockResource);
147        when(mockResource.getAcl()).thenReturn(mockAclResource);
148
149        when(mockParentResource.getId()).thenReturn(addPrefix(parentPath));
150        when(mockParentResource.getAcl()).thenReturn(mockAclResource);
151        when(mockAclResource.isAcl()).thenReturn(true);
152        when(mockAclResource.getId()).thenReturn(addPrefix(parentPath) + "/fcr:acl");
153
154        when(mockAclResource.getTriples())
155                .thenReturn(getRdfStreamFromResource(acl, TTL));
156
157        final Map<String, Collection<String>> roles = roleProvider.getRoles(mockResource, mockTransaction);
158
159        assertEquals("There should be exactly one agent in the role map", 1, roles.size());
160        assertEquals("The agent should have exactly two modes", 2, roles.get(agent).size());
161        assertTrue("The agent should be able to read", roles.get(agent).contains(WEBAC_MODE_READ_VALUE));
162        assertTrue("The agent should be able to write", roles.get(agent).contains(WEBAC_MODE_WRITE_VALUE));
163    }
164
165    @Test
166    public void acl21NoDefaultACLStatementTest() throws RepositoryException {
167        final String agent = "user21";
168        final String parentPath = "/resource_acl_no_inheritance";
169        final String accessTo = parentPath + "/foo";
170        final String acl = "/acls/21/acl.ttl";
171
172        when(mockResource.getAcl()).thenReturn(null);
173        when(mockParentResource.getAcl()).thenReturn(mockAclResource);
174        when(mockAclResource.hasProperty("acl:default")).thenReturn(false);
175
176        when(mockResource.getId()).thenReturn(addPrefix(accessTo));
177        when(mockResource.getContainer()).thenReturn(mockParentResource);
178        when(mockResource.getOriginalResource()).thenReturn(mockResource);
179        when(mockResource.getAcl()).thenReturn(mockAclResource);
180
181        when(mockParentResource.getId()).thenReturn(addPrefix(parentPath));
182        when(mockAclResource.getId()).thenReturn(addPrefix(acl));
183        when(mockParentResource.getAcl()).thenReturn(null);
184
185
186        when(mockAclResource.getTriples())
187                .thenReturn(getRdfStreamFromResource(acl, TTL));
188
189        System.setProperty(ROOT_AUTHORIZATION_PROPERTY, "./target/test-classes/test-root-authorization2.ttl");
190
191        // The default root ACL should be used for authorization instead of the parent ACL
192        final String rootAgent = "user06a";
193        final Map<String, Collection<String>> roles = roleProvider.getRoles(mockResource, mockTransaction);
194        assertEquals("Contains no agents in the role map!", 1, roles.size());
195        assertNull("Contains agent " + agent + " from ACL in parent node!", roles.get(agent));
196        assertEquals("Should have agent " + rootAgent + " from the root ACL!", 1, roles.get(rootAgent).size());
197        assertTrue("Should have read mode for agent " + rootAgent + " from the root ACL!",
198                roles.get(rootAgent).contains(WEBAC_MODE_READ_VALUE));
199    }
200
201    @Test
202    public void acl01Test1() throws RepositoryException, PathNotFoundException {
203        final String agent = "user01";
204        final String accessTo = "/webacl_box1";
205        final String acl = "/acls/01/acl.ttl";
206
207        when(mockResource.getAcl()).thenReturn(mockAclResource);
208        when(mockResourceFactory.getResource(mockTransaction.getId(), FedoraId.create(acl)))
209                .thenReturn(mockAclResource);
210        when(mockAclResource.getId()).thenReturn(addPrefix(acl));
211        when(mockResource.getId()).thenReturn(addPrefix(accessTo));
212        when(mockResource.getOriginalResource()).thenReturn(mockResource);
213        when(mockAclResource.getTriples())
214            .thenReturn(getRdfStreamFromResource(acl, TTL));
215        when(mockAclResource.isAcl()).thenReturn(true);
216        when(mockAclResource.getId()).thenReturn(addPrefix(accessTo) + "/fcr:acl");
217
218
219        final Map<String, Collection<String>> roles = roleProvider.getRoles(mockResource, mockTransaction);
220
221        assertEquals("There should be exactly one agent in the role map", 1, roles.size());
222        assertEquals("The agent should have exactly two modes", 2, roles.get(agent).size());
223        assertTrue("The agent should be able to read", roles.get(agent).contains(WEBAC_MODE_READ_VALUE));
224        assertTrue("The agent should be able to write", roles.get(agent).contains(WEBAC_MODE_WRITE_VALUE));
225    }
226
227    @Ignore // TODO FIX THIS TEST
228    @Test
229    public void acl01Test2() throws RepositoryException, PathNotFoundException {
230        final String accessTo = "/webacl_box2";
231        final String acl = "/acls/01/acl.ttl";
232
233        when(mockResource.getAcl()).thenReturn(mockAclResource);
234        when(mockResourceFactory.getResource(mockTransaction.getId(), FedoraId.create(acl))).thenReturn(
235                mockAclResource);
236        when(mockAclResource.getId()).thenReturn(addPrefix(acl));
237        when(mockResource.getId()).thenReturn(addPrefix(accessTo));
238        when(mockResource.getOriginalResource()).thenReturn(mockResource);
239        when(mockAclResource.getTriples())
240            .thenReturn(getRdfStreamFromResource(acl, TTL));
241
242        final Map<String, Collection<String>> roles = roleProvider.getRoles(mockResource, mockTransaction);
243
244        assertOnlyDefaultAgentInRoles(roles);
245    }
246
247    @Test
248    public void acl02Test() throws RepositoryException {
249        final String agent = "Editors";
250        final String accessTo = "/box/bag/collection";
251        final String acl = "/acls/02/acl.ttl";
252
253        when(mockResource.getAcl()).thenReturn(mockAclResource);
254        when(mockAclResource.getId()).thenReturn(addPrefix(acl));
255        when(mockResource.getId()).thenReturn(addPrefix(accessTo));
256        when(mockAclResource.getTriples())
257            .thenReturn(getRdfStreamFromResource(acl, TTL));
258        when(mockAclResource.isAcl()).thenReturn(true);
259        when(mockAclResource.getId()).thenReturn(addPrefix(accessTo) + "/fcr:acl");
260
261        when(mockResource.getOriginalResource()).thenReturn(mockResource);
262
263
264        final Map<String, Collection<String>> roles = roleProvider.getRoles(mockResource, mockTransaction);
265
266        assertEquals("There should be exactly one agent in the role map", 1, roles.size());
267        assertEquals("The agent should have exactly two modes", 2, roles.get(agent).size());
268        assertTrue("The agent should be able to read", roles.get(agent).contains(WEBAC_MODE_READ_VALUE));
269        assertTrue("The agent should be able to write", roles.get(agent).contains(WEBAC_MODE_WRITE_VALUE));
270    }
271
272    @Test
273    public void acl03Test1() throws RepositoryException, PathNotFoundException {
274        final String agent = "http://xmlns.com/foaf/0.1/Agent";
275        final String accessTo = "/dark/archive/sunshine";
276        final String acl = "/acls/03/acl.ttl";
277
278        when(mockResource.getAcl()).thenReturn(mockAclResource);
279        when(mockResourceFactory.getResource(mockTransaction.getId(), FedoraId.create(acl))).thenReturn(
280                mockAclResource);
281        when(mockAclResource.getId()).thenReturn(addPrefix(acl));
282        when(mockResource.getId()).thenReturn(addPrefix(accessTo));
283        when(mockResource.getOriginalResource()).thenReturn(mockResource);
284        when(mockAclResource.getTriples())
285            .thenReturn(getRdfStreamFromResource(acl, TTL));
286        when(mockAclResource.isAcl()).thenReturn(true);
287        when(mockAclResource.getId()).thenReturn(addPrefix(accessTo) + "/fcr:acl");
288
289        final Map<String, Collection<String>> roles = roleProvider.getRoles(mockResource, mockTransaction);
290
291        assertEquals("There should be exactly one agent in the roles map", 1, roles.size());
292        assertEquals("The agent should have exactly one mode", 1, roles.get(agent).size());
293        assertTrue("The agent should be able to read", roles.get(agent).contains(WEBAC_MODE_READ_VALUE));
294    }
295
296    @Test
297    public void acl03Test2() throws RepositoryException, PathNotFoundException {
298        final String agent = "Restricted";
299        final String accessTo = "/dark/archive";
300        final String acl = "/acls/03/acl.ttl";
301
302        when(mockResource.getAcl()).thenReturn(mockAclResource);
303        when(mockAclResource.isAcl()).thenReturn(true);
304        when(mockResourceFactory.getResource(mockTransaction.getId(), FedoraId.create(acl))).thenReturn(
305                mockAclResource);
306        when(mockAclResource.getId()).thenReturn(addPrefix(acl));
307        when(mockResource.getId()).thenReturn(addPrefix(accessTo));
308        when(mockResource.getOriginalResource()).thenReturn(mockResource);
309        when(mockAclResource.getTriples())
310            .thenReturn(getRdfStreamFromResource(acl, TTL));
311
312        final Map<String, Collection<String>> roles = roleProvider.getRoles(mockResource, mockTransaction);
313
314        assertEquals("There should be exactly one agent", 1, roles.size());
315        assertEquals("The agent should have one mode", 1, roles.get(agent).size());
316        assertTrue("The agent should be able to read", roles.get(agent).contains(WEBAC_MODE_READ_VALUE));
317    }
318
319    @Test
320    public void foafAgentTest() throws RepositoryException, PathNotFoundException {
321        final String agent = "http://xmlns.com/foaf/0.1/Agent";
322        final String accessTo = "/foaf-agent";
323        final String acl = "/acls/03/foaf-agent.ttl";
324
325        when(mockResource.getAcl()).thenReturn(mockAclResource);
326        when(mockResourceFactory.getResource(mockTransaction.getId(), FedoraId.create(acl)))
327                .thenReturn(mockAclResource);
328        when(mockAclResource.getId()).thenReturn(addPrefix(acl));
329        when(mockAclResource.isAcl()).thenReturn(true);
330        when(mockResource.getId()).thenReturn(addPrefix(accessTo));
331        when(mockResource.getOriginalResource()).thenReturn(mockResource);
332        when(mockAclResource.getTriples())
333            .thenReturn(getRdfStreamFromResource(acl, TTL));
334
335        final Map<String, Collection<String>> roles = roleProvider.getRoles(mockResource, mockTransaction);
336
337        assertEquals("There should be only one valid role", 1, roles.size());
338        assertEquals("The foaf:Agent should have exactly one valid mode", 1,
339                     roles.get(agent).size());
340        assertTrue("The foaf:Agent should be able to write",
341                   roles.get(agent).contains(WEBAC_MODE_READ_VALUE));
342    }
343
344    @Test
345    public void authenticatedAgentTest() throws RepositoryException, PathNotFoundException {
346        final String aclAuthenticatedAgent = "http://www.w3.org/ns/auth/acl#AuthenticatedAgent";
347        final String accessTo = "/authenticated-agent";
348        final String acl = "/acls/03/authenticated-agent.ttl";
349
350        when(mockResource.getAcl()).thenReturn(mockAclResource);
351        when(mockResourceFactory.getResource(mockTransaction.getId(), FedoraId.create(acl))).thenReturn(
352                mockAclResource);
353        when(mockAclResource.getId()).thenReturn(addPrefix(acl));
354        when(mockAclResource.isAcl()).thenReturn(true);
355        when(mockResource.getId()).thenReturn(addPrefix(accessTo));
356        when(mockResource.getOriginalResource()).thenReturn(mockResource);
357        when(mockAclResource.getTriples()).thenReturn(getRdfStreamFromResource(acl, TTL));
358
359        final Map<String, Collection<String>> roles = roleProvider.getRoles(mockResource, mockTransaction);
360
361        assertEquals("There should be only one valid role", 1, roles.size());
362        assertEquals("The acl:AuthenticatedAgent should have exactly one valid mode", 1,
363                     roles.get(aclAuthenticatedAgent).size());
364        assertTrue("The acl:AuthenticatedAgent should be able to write",
365                   roles.get(aclAuthenticatedAgent).contains(WEBAC_MODE_READ_VALUE));
366    }
367
368    @Test
369    public void acl04Test() throws RepositoryException, PathNotFoundException {
370        final String agent1 = "http://xmlns.com/foaf/0.1/Agent";
371        final String agent2 = "Editors";
372        final String accessTo = "/public_collection";
373        final String acl = "/acls/04/acl.ttl";
374
375        when(mockResource.getAcl()).thenReturn(mockAclResource);
376        when(mockResourceFactory.getResource(mockTransaction.getId(), FedoraId.create(acl))).thenReturn(
377                mockAclResource);
378        when(mockAclResource.getId()).thenReturn(addPrefix(acl));
379        when(mockAclResource.isAcl()).thenReturn(true);
380        when(mockResource.getId()).thenReturn(addPrefix(accessTo));
381        when(mockResource.getOriginalResource()).thenReturn(mockResource);
382        when(mockAclResource.getTriples()).thenReturn(getRdfStreamFromResource(acl, TTL));
383
384        final Map<String, Collection<String>> roles = roleProvider.getRoles(mockResource, mockTransaction);
385
386        assertEquals("There should be exactly two agents", 2, roles.size());
387        assertEquals("The agent should have one mode", 1, roles.get(agent1).size());
388        assertTrue("The agent should be able to read", roles.get(agent1).contains(WEBAC_MODE_READ_VALUE));
389        assertEquals("The agent should have two modes", 2, roles.get(agent2).size());
390        assertTrue("The agent should be able to read", roles.get(agent2).contains(WEBAC_MODE_READ_VALUE));
391        assertTrue("The agent should be able to write", roles.get(agent2).contains(WEBAC_MODE_READ_VALUE));
392    }
393
394    @Test
395    public void acl05Test() throws RepositoryException, PathNotFoundException {
396        final String agent1 = "http://xmlns.com/foaf/0.1/Agent";
397        final String agent2 = "Admins";
398        final String accessTo = "/mixedCollection";
399        final String acl = "/acls/05/acl.ttl";
400
401        when(mockResource.getAcl()).thenReturn(mockAclResource);
402        when(mockResourceFactory.getResource(mockTransaction.getId(), FedoraId.create(addPrefix(acl)))).thenReturn(
403                mockAclResource
404        );
405        when(mockResource.getTypes()).thenReturn(singletonList(URI.create("http://example.com/terms#publicImage")));
406        when(mockAclResource.isAcl()).thenReturn(true);
407        when(mockAclResource.getId()).thenReturn(addPrefix(acl));
408        when(mockResource.getId()).thenReturn(addPrefix(accessTo));
409        when(mockResource.getOriginalResource()).thenReturn(mockResource);
410        when(mockAclResource.getTriples()).thenReturn(getRdfStreamFromResource(acl, TTL));
411
412        final Map<String, Collection<String>> roles = roleProvider.getRoles(mockResource, mockTransaction);
413
414        assertEquals("There should be exactly two agents", 2, roles.size());
415        assertEquals("The agent should have one mode", 1, roles.get(agent1).size());
416        assertTrue("The agent should be able to read", roles.get(agent1).contains(WEBAC_MODE_READ_VALUE));
417        assertEquals("The agent should have one mode", 1, roles.get(agent2).size());
418        assertTrue("The agent should be able to read", roles.get(agent2).contains(WEBAC_MODE_READ_VALUE));
419    }
420
421    @Test
422    public void acl05Test2() throws RepositoryException, PathNotFoundException {
423        final String agent1 = "http://xmlns.com/foaf/0.1/Agent";
424        final String accessTo = "/someOtherCollection";
425        final String acl = "/acls/05/acl.ttl";
426
427        when(mockResourceFactory.getResource(mockTransaction.getId(), FedoraId.create(addPrefix(acl))))
428                .thenReturn(mockAclResource);
429        when(mockResource.getAcl()).thenReturn(mockAclResource);
430        when(mockResource.getTypes()).thenReturn(singletonList(URI.create("http://example.com/terms#publicImage")));
431        when(mockResource.getId()).thenReturn(addPrefix(accessTo));
432        when(mockResource.getOriginalResource()).thenReturn(mockResource);
433        when(mockAclResource.getId()).thenReturn(addPrefix(acl));
434        when(mockAclResource.isAcl()).thenReturn(true);
435        when(mockAclResource.getTriples()).thenReturn(getRdfStreamFromResource(acl, TTL));
436
437        final Map<String, Collection<String>> roles = roleProvider.getRoles(mockResource, mockTransaction);
438
439        assertEquals("There should be exactly one agent", 1, roles.size());
440        assertEquals("The agent should have one mode", 1, roles.get(agent1).size());
441        assertTrue("The agent should be able to read", roles.get(agent1).contains(WEBAC_MODE_READ_VALUE));
442    }
443
444    /* (non-Javadoc)
445     * Test that an in-repository resource used as a target for acl:agentGroup has
446     * the rdf:type of vcard:Group. This test mocks a vcard:Group resource and should
447     * therefore retrieve two agents.
448     */
449    @Test
450    public void acl09Test1() throws RepositoryException, PathNotFoundException {
451        final String agent1 = "person1";
452        final String accessTo = "/anotherCollection";
453
454        final String groupResource = "/group/foo";
455        final String aclDir = "/acls/09";
456        final String acl = aclDir + "/acl.ttl";
457        final String group = aclDir + "/group.ttl";
458
459        when(mockResourceFactory.getResource(mockTransaction, FedoraId.create(addPrefix(acl))))
460                .thenReturn(mockAclResource);
461        when(mockResourceFactory.getResource(mockTransaction, FedoraId.create(addPrefix(groupResource))))
462                .thenReturn(mockAgentClassResource);
463        when(mockResource.getAcl()).thenReturn(mockAclResource);
464        when(mockResource.getId()).thenReturn(addPrefix(accessTo));
465        when(mockResource.getOriginalResource()).thenReturn(mockResource);
466        when(mockAclResource.getTriples()).thenReturn(getRdfStreamFromResource(acl, TTL));
467        when(mockAclResource.isAcl()).thenReturn(true);
468        when(mockAclResource.getId()).thenReturn(addPrefix(accessTo) + "/fcr:acl");
469
470        when(mockAgentClassResource.getTypes()).thenReturn(singletonList(VCARD_GROUP));
471        when(mockAgentClassResource.getId()).thenReturn(addPrefix(groupResource));
472        when(mockAgentClassResource.getTriples()).thenReturn(getRdfStreamFromResource(group, TTL));
473
474
475        final Map<String, Collection<String>> roles = roleProvider.getRoles(mockResource, mockTransaction);
476
477        assertEquals("There should be exactly two agents", 2, roles.size());
478        assertEquals("The agent should have two modes", 2, roles.get(agent1).size());
479        assertTrue("The agent should be able to read", roles.get(agent1).contains(WEBAC_MODE_READ_VALUE));
480        assertTrue("The agent should be able to write", roles.get(agent1).contains(WEBAC_MODE_WRITE_VALUE));
481    }
482
483    /* (non-Javadoc)
484     * Test that an in-repository resource used as a target for acl:agentClass has
485     * the rdf:type of foaf:Group. This test mocks a resource that is not of the type
486     * foaf:Group and therefore should retrieve zero agents.
487     */
488    @Ignore // TODO FIX THIS TEST
489    @Test
490    public void acl09Test2() throws RepositoryException, PathNotFoundException {
491        final String accessTo = "/anotherCollection";
492
493        final String groupResource = "/group/foo";
494        final String acl = "/acls/09/acl.ttl";
495        final String group = "/acls/09/group.ttl";
496
497        when(mockResourceFactory.getResource(mockTransaction.getId(), FedoraId.create(addPrefix(acl)))).thenReturn(
498                mockAclResource);
499        when(mockResourceFactory.getResource(mockTransaction.getId(),
500                FedoraId.create(addPrefix(groupResource)))).thenReturn(mockAgentClassResource);
501        when(mockResource.getAcl()).thenReturn(mockAclResource);
502        when(mockResource.getId()).thenReturn(addPrefix(accessTo));
503        when(mockResource.getOriginalResource()).thenReturn(mockResource);
504        when(mockAclResource.getId()).thenReturn(addPrefix(acl));
505        when(mockAclResource.getTriples()).thenReturn(getRdfStreamFromResource(acl, TTL));
506
507        when(mockAgentClassResource.getTypes()).thenReturn(new ArrayList<>());
508        when(mockAgentClassResource.getId()).thenReturn(addPrefix(groupResource));
509        when(mockAgentClassResource.getTriples())
510            .thenReturn(getRdfStreamFromResource(group, TTL));
511
512        final Map<String, Collection<String>> roles = roleProvider.getRoles(mockResource, mockTransaction);
513
514        assertOnlyDefaultAgentInRoles(roles);
515    }
516
517    @Test
518    public void acl17Test1() throws RepositoryException, PathNotFoundException {
519        final String foafAgent = "http://xmlns.com/foaf/0.1/Agent";
520        final String accessTo = "/dark/archive/sunshine";
521        final String acl = "/acls/17/acl.ttl";
522
523        when(mockResource.getAcl()).thenReturn(mockAclResource);
524        when(mockResourceFactory.getResource(mockTransaction.getId(), FedoraId.create(addPrefix(acl))))
525                .thenReturn(mockAclResource);
526        when(mockAclResource.getId()).thenReturn(addPrefix(acl));
527        when(mockAclResource.isAcl()).thenReturn(true);
528        when(mockResource.getId()).thenReturn(addPrefix(accessTo));
529        when(mockResource.getOriginalResource()).thenReturn(mockResource);
530        when(mockAclResource.getTriples())
531            .thenReturn(getRdfStreamFromResource(acl, TTL));
532
533        final Map<String, Collection<String>> roles = roleProvider.getRoles(mockResource, mockTransaction);
534
535        assertEquals("There should be only one valid role", 1, roles.size());
536        assertEquals("The foafAgent should have exactly one valid mode", 1, roles.get(foafAgent).size());
537        assertTrue("The foafAgent should be able to write", roles.get(foafAgent).contains(WEBAC_MODE_WRITE_VALUE));
538    }
539
540    @Test
541    public void noAclTest1() {
542        final String agent1 = "http://xmlns.com/foaf/0.1/Agent";
543
544        when(mockResource.getAcl()).thenReturn(null);
545
546        when(mockResource.getId()).thenReturn(FEDORA_ID_PREFIX);
547        when(mockResource.getTypes()).thenReturn(
548                singletonList(FEDORA_RESOURCE_URI));
549        when(mockResource.getOriginalResource()).thenReturn(mockResource);
550        final Map<String, Collection<String>> roles = roleProvider.getRoles(mockResource, mockTransaction);
551
552        assertEquals("There should be exactly one agent", 1, roles.size());
553        assertEquals("The agent should have one mode", 1, roles.get(agent1).size());
554    }
555
556    @Test(expected = RuntimeException.class)
557    public void noAclTestMalformedRdf2() {
558
559        when(mockResource.getAcl()).thenReturn(null);
560
561        when(mockResource.getId()).thenReturn(FEDORA_ID_PREFIX);
562        when(mockResource.getTypes()).thenReturn(
563                singletonList(FEDORA_RESOURCE_URI));
564        when(mockResource.getOriginalResource()).thenReturn(mockResource);
565
566        System.setProperty(ROOT_AUTHORIZATION_PROPERTY, "./target/test-classes/logback-test.xml");
567        roleProvider.getRoles(mockResource, mockTransaction);
568    }
569
570    @Test
571    public void noAclTestOkRdf3() {
572        final String agent1 = "testAdminUser";
573
574        when(mockResource.getAcl()).thenReturn(null);
575        when(mockResource.getId()).thenReturn(FEDORA_ID_PREFIX);
576        when(mockResource.getTypes()).thenReturn(
577                singletonList(FEDORA_RESOURCE_URI));
578
579        System.setProperty(ROOT_AUTHORIZATION_PROPERTY, "./target/test-classes/test-root-authorization.ttl");
580        final Map<String, Collection<String>> roles = roleProvider.getRoles(mockResource, mockTransaction);
581        System.clearProperty(ROOT_AUTHORIZATION_PROPERTY);
582
583        assertEquals("There should be exactly one agent", 1, roles.size());
584        assertEquals("The agent should have one mode", 1, roles.get(agent1).size());
585        assertTrue("The agent should be able to read", roles.get(agent1).contains(WEBAC_MODE_READ_VALUE));
586    }
587
588    private static RdfStream getRdfStreamFromResource(final String resourcePath, final Lang lang) {
589        final Model model = createDefaultModel();
590
591        RDFDataMgr.read(model, WebACRolesProviderTest.class.getResourceAsStream(resourcePath), lang);
592
593        final List<Triple> triples = new ArrayList<>();
594        model.listStatements().forEachRemaining(x -> {
595            final Triple t = x.asTriple();
596            if (t.getObject().isURI() && t.getObject().getURI().startsWith(FEDORA_URI_PREFIX)) {
597                triples.add(new Triple(t.getSubject(), t.getPredicate(),
598                        createURI(FEDORA_PREFIX + t.getObject().getURI().substring(FEDORA_URI_PREFIX.length()))));
599            } else {
600                triples.add(t);
601            }
602        });
603
604        return new DefaultRdfStream(createURI("subject"), triples.stream());
605    }
606
607    private String addPrefix(final String id) {
608        final String cleanId = id.replaceFirst("^/", "");
609        if (!cleanId.startsWith(FEDORA_ID_PREFIX)) {
610            return FEDORA_ID_PREFIX + "/" + cleanId;
611        }
612        return cleanId;
613    }
614
615}