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