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