001/**
002 * Copyright 2015 DuraSpace, Inc.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.fcrepo.auth.webac;
017
018import static com.hp.hpl.jena.graph.NodeFactory.createURI;
019import static com.hp.hpl.jena.rdf.model.ModelFactory.createDefaultModel;
020import static org.apache.jena.riot.Lang.TTL;
021import static org.fcrepo.auth.webac.URIConstants.FOAF_GROUP;
022import static org.fcrepo.auth.webac.URIConstants.WEBAC_ACCESS_CONTROL_VALUE;
023import static org.fcrepo.auth.webac.URIConstants.WEBAC_AUTHORIZATION;
024import static org.fcrepo.auth.webac.URIConstants.WEBAC_MODE_READ_VALUE;
025import static org.fcrepo.auth.webac.URIConstants.WEBAC_MODE_WRITE_VALUE;
026import static org.fcrepo.auth.webac.WebACRolesProvider.ROOT_AUTHORIZATION_PROPERTY;
027import static org.fcrepo.kernel.api.RdfLexicon.REPOSITORY_NAMESPACE;
028import static org.junit.Assert.assertEquals;
029import static org.junit.Assert.assertTrue;
030import static org.mockito.Matchers.anyObject;
031import static org.mockito.Matchers.eq;
032import static org.mockito.Mockito.when;
033import static org.springframework.test.util.ReflectionTestUtils.setField;
034
035import java.net.URI;
036import java.util.Arrays;
037import java.util.ArrayList;
038import java.util.List;
039import java.util.Map;
040
041import javax.jcr.Node;
042import javax.jcr.RepositoryException;
043import javax.jcr.Property;
044import javax.jcr.Session;
045
046import com.hp.hpl.jena.graph.Triple;
047import com.hp.hpl.jena.rdf.model.Model;
048import org.apache.jena.riot.Lang;
049import org.apache.jena.riot.RDFDataMgr;
050import org.fcrepo.auth.roles.common.AccessRolesProvider;
051import org.fcrepo.http.commons.session.SessionFactory;
052import org.fcrepo.kernel.api.models.FedoraResource;
053import org.fcrepo.kernel.api.services.NodeService;
054import org.fcrepo.kernel.api.utils.iterators.RdfStream;
055import org.fcrepo.kernel.modeshape.rdf.impl.PropertiesRdfContext;
056import org.junit.Before;
057import org.junit.Test;
058import org.junit.runner.RunWith;
059import org.mockito.Mock;
060import org.mockito.runners.MockitoJUnitRunner;
061
062/**
063 * @author acoburn
064 * @since 9/3/15
065 */
066@RunWith(MockitoJUnitRunner.class)
067public class WebACRolesProviderTest {
068
069    private AccessRolesProvider roleProvider;
070
071    private static final String FEDORA_PREFIX = "info:fedora";
072    private static final String FEDORA_URI_PREFIX = "file:///rest";
073
074    @Mock
075    private Node mockNode;
076
077    @Mock
078    private Node mockParentNode;
079
080    @Mock
081    private Session mockSession;
082
083    @Mock
084    private SessionFactory mockSessionFactory;
085
086    @Mock
087    private NodeService mockNodeService;
088
089    @Mock
090    private FedoraResource mockResource;
091
092    @Mock
093    private FedoraResource mockParentResource;
094
095    @Mock
096    private FedoraResource mockAclResource;
097
098    @Mock
099    private FedoraResource mockAgentClassResource;
100
101    @Mock
102    private FedoraResource mockAuthorizationResource1;
103
104    @Mock
105    private FedoraResource mockAuthorizationResource2;
106
107    @Mock
108    private Property mockProperty;
109
110    @Before
111    public void setUp() throws RepositoryException {
112
113        roleProvider = new WebACRolesProvider();
114        setField(roleProvider, "nodeService", mockNodeService);
115        setField(roleProvider, "sessionFactory", mockSessionFactory);
116
117        when(mockNodeService.cast(mockNode)).thenReturn(mockResource);
118        when(mockNode.getSession()).thenReturn(mockSession);
119        when(mockSessionFactory.getInternalSession()).thenReturn(mockSession);
120
121        when(mockResource.getNode()).thenReturn(mockNode);
122        when(mockNode.getDepth()).thenReturn(0);
123    }
124
125    @Test
126    public void noAclTest() throws RepositoryException {
127        final String accessTo = "/dark/archive/sunshine";
128
129        when(mockResource.getPath()).thenReturn(accessTo);
130        when(mockResource.getContainer()).thenReturn(mockParentResource);
131        when(mockResource.getTriples(anyObject(), eq(PropertiesRdfContext.class)))
132                .thenReturn(new RdfStream());
133        when(mockNode.getDepth()).thenReturn(1);
134
135        when(mockParentResource.getNode()).thenReturn(mockParentNode);
136        when(mockParentResource.getTriples(anyObject(), eq(PropertiesRdfContext.class)))
137                .thenReturn(new RdfStream());
138        when(mockParentNode.getDepth()).thenReturn(0);
139
140        final Map<String, List<String>> roles = roleProvider.getRoles(mockNode, true);
141
142        assertTrue("There should be no agents in the roles map", roles.isEmpty());
143    }
144
145    @Test
146    public void acl01ParentTest() throws RepositoryException {
147        final String agent = "smith123";
148        final String accessTo = "/webacl_box1";
149        final String acl = "/acls/01";
150        final String auth = acl + "/authorization.ttl";
151
152        when(mockResource.getPath()).thenReturn(accessTo);
153        when(mockResource.getContainer()).thenReturn(mockParentResource);
154        when(mockResource.getPath()).thenReturn(accessTo + "/foo");
155        when(mockResource.getTriples(anyObject(), eq(PropertiesRdfContext.class)))
156                .thenReturn(new RdfStream());
157        when(mockNode.getDepth()).thenReturn(1);
158
159        when(mockParentResource.getNode()).thenReturn(mockParentNode);
160        when(mockParentResource.getPath()).thenReturn(accessTo);
161        when(mockParentResource.getTriples(anyObject(), eq(PropertiesRdfContext.class)))
162                .thenReturn(getResourceRdfStream(accessTo, acl));
163        when(mockParentNode.getDepth()).thenReturn(0);
164
165        when(mockProperty.getString()).thenReturn(acl);
166        when(mockNodeService.find(mockSession, acl)).thenReturn(mockAclResource);
167        when(mockAclResource.getPath()).thenReturn(acl);
168
169        when(mockAuthorizationResource1.getTypes()).thenReturn(Arrays.asList(WEBAC_AUTHORIZATION));
170        when(mockAuthorizationResource1.getPath()).thenReturn(auth);
171        when(mockAuthorizationResource1.getTriples(anyObject(), eq(PropertiesRdfContext.class)))
172                .thenReturn(getRdfStreamFromResource(auth, TTL));
173
174        when(mockAclResource.getChildren()).thenReturn(Arrays.asList(mockAuthorizationResource1).iterator());
175
176        final Map<String, List<String>> roles = roleProvider.getRoles(mockNode, true);
177
178        assertEquals("There should be exactly one agent in the role map", 1, roles.size());
179        assertEquals("The agent should have exactly two modes", 2, roles.get(agent).size());
180        assertTrue("The agent should be able to read", roles.get(agent).contains(WEBAC_MODE_READ_VALUE));
181        assertTrue("The agent should be able to write", roles.get(agent).contains(WEBAC_MODE_WRITE_VALUE));
182    }
183
184    @Test
185    public void acl01Test1() throws RepositoryException {
186        final String agent = "smith123";
187        final String accessTo = "/webacl_box1";
188        final String acl = "/acls/01";
189        final String auth = acl + "/authorization.ttl";
190
191        when(mockNodeService.find(mockSession, acl)).thenReturn(mockAclResource);
192        when(mockProperty.getString()).thenReturn(acl);
193        when(mockAclResource.getPath()).thenReturn(acl);
194        when(mockResource.getPath()).thenReturn(accessTo);
195        when(mockResource.getTriples(anyObject(), eq(PropertiesRdfContext.class)))
196                .thenReturn(getResourceRdfStream(accessTo, acl));
197
198        when(mockAuthorizationResource1.getTypes()).thenReturn(Arrays.asList(WEBAC_AUTHORIZATION));
199        when(mockAuthorizationResource1.getPath()).thenReturn(auth);
200        when(mockAuthorizationResource1.getTriples(anyObject(), eq(PropertiesRdfContext.class)))
201                .thenReturn(getRdfStreamFromResource(auth, TTL));
202
203        when(mockAclResource.getChildren()).thenReturn(Arrays.asList(mockAuthorizationResource1).iterator());
204
205        final Map<String, List<String>> roles = roleProvider.getRoles(mockNode, true);
206
207        assertEquals("There should be exactly one agent in the role map", 1, roles.size());
208        assertEquals("The agent should have exactly two modes", 2, roles.get(agent).size());
209        assertTrue("The agent should be able to read", roles.get(agent).contains(WEBAC_MODE_READ_VALUE));
210        assertTrue("The agent should be able to write", roles.get(agent).contains(WEBAC_MODE_WRITE_VALUE));
211    }
212
213    @Test
214    public void acl01Test2() throws RepositoryException {
215        final String accessTo = "/webacl_box2";
216        final String acl = "/acls/01";
217        final String auth = acl + "/authorization.ttl";
218
219        when(mockNodeService.find(mockSession, acl)).thenReturn(mockAclResource);
220        when(mockProperty.getString()).thenReturn(acl);
221        when(mockAclResource.getPath()).thenReturn(acl);
222        when(mockResource.getPath()).thenReturn(accessTo);
223        when(mockResource.getTriples(anyObject(), eq(PropertiesRdfContext.class)))
224                .thenReturn(getResourceRdfStream(accessTo, acl));
225
226        when(mockAuthorizationResource1.getTypes()).thenReturn(Arrays.asList(WEBAC_AUTHORIZATION));
227        when(mockAuthorizationResource1.getPath()).thenReturn(auth);
228        when(mockAuthorizationResource1.getTriples(anyObject(), eq(PropertiesRdfContext.class)))
229                .thenReturn(getRdfStreamFromResource(auth, TTL));
230
231        when(mockAclResource.getChildren()).thenReturn(Arrays.asList(mockAuthorizationResource1).iterator());
232
233        final Map<String, List<String>> roles = roleProvider.getRoles(mockNode, true);
234
235        assertTrue("There should be no agents associated with this object", roles.isEmpty());
236    }
237
238    @Test
239    public void acl02Test() throws RepositoryException {
240        final String agent = "Editors";
241        final String accessTo = "/box/bag/collection";
242        final String acl = "/acls/02";
243        final String auth = acl + "/authorization.ttl";
244
245        when(mockNodeService.find(mockSession, acl)).thenReturn(mockAclResource);
246        when(mockProperty.getString()).thenReturn(acl);
247        when(mockAclResource.getPath()).thenReturn(acl);
248        when(mockResource.getPath()).thenReturn(accessTo);
249        when(mockResource.getTriples(anyObject(), eq(PropertiesRdfContext.class)))
250                .thenReturn(getResourceRdfStream(accessTo, acl));
251
252        when(mockAuthorizationResource1.getTypes()).thenReturn(Arrays.asList(WEBAC_AUTHORIZATION));
253        when(mockAuthorizationResource1.getPath()).thenReturn(auth);
254        when(mockAuthorizationResource1.getTriples(anyObject(), eq(PropertiesRdfContext.class)))
255                .thenReturn(getRdfStreamFromResource(auth, TTL));
256
257        when(mockAclResource.getChildren()).thenReturn(Arrays.asList(mockAuthorizationResource1).iterator());
258
259        final Map<String, List<String>> roles = roleProvider.getRoles(mockNode, true);
260
261        assertEquals("There should be exactly one agent in the role map", 1, roles.size());
262        assertEquals("The agent should have exactly two modes", 2, roles.get(agent).size());
263        assertTrue("The agent should be able to read", roles.get(agent).contains(WEBAC_MODE_READ_VALUE));
264        assertTrue("The agent should be able to write", roles.get(agent).contains(WEBAC_MODE_WRITE_VALUE));
265    }
266
267    @Test
268    public void acl03Test1() throws RepositoryException {
269        final String agent = "http://xmlns.com/foaf/0.1/Agent";
270        final String accessTo = "/dark/archive/sunshine";
271        final String acl = "/acls/03";
272        final String auth1 = acl + "/auth_restricted.ttl";
273        final String auth2 = acl + "/auth_open.ttl";
274
275        when(mockNodeService.find(mockSession, acl)).thenReturn(mockAclResource);
276        when(mockProperty.getString()).thenReturn(acl);
277        when(mockAclResource.getPath()).thenReturn(acl);
278        when(mockResource.getPath()).thenReturn(accessTo);
279        when(mockResource.getTriples(anyObject(), eq(PropertiesRdfContext.class)))
280                .thenReturn(getResourceRdfStream(accessTo, acl));
281
282        when(mockAuthorizationResource1.getTypes()).thenReturn(Arrays.asList(WEBAC_AUTHORIZATION));
283        when(mockAuthorizationResource1.getPath()).thenReturn(auth1);
284        when(mockAuthorizationResource1.getTriples(anyObject(), eq(PropertiesRdfContext.class)))
285                .thenReturn(getRdfStreamFromResource(auth1, TTL));
286
287        when(mockAuthorizationResource2.getTypes()).thenReturn(Arrays.asList(WEBAC_AUTHORIZATION));
288        when(mockAuthorizationResource2.getPath()).thenReturn(auth2);
289        when(mockAuthorizationResource2.getTriples(anyObject(), eq(PropertiesRdfContext.class)))
290                .thenReturn(getRdfStreamFromResource(auth2, TTL));
291
292        when(mockAclResource.getChildren()).thenReturn(
293                Arrays.asList(mockAuthorizationResource1, mockAuthorizationResource2).iterator());
294
295        final Map<String, List<String>> roles = roleProvider.getRoles(mockNode, true);
296
297        assertEquals("There should be exactly one agent in the roles map", 1, roles.size());
298        assertEquals("The agent should have exactly one mode", 1, roles.get(agent).size());
299        assertTrue("The agent should be able to read", roles.get(agent).contains(WEBAC_MODE_READ_VALUE));
300    }
301
302    @Test
303    public void acl03Test2() throws RepositoryException {
304        final String agent = "Restricted";
305        final String accessTo = "/dark/archive";
306        final String acl = "/acls/03";
307        final String auth1 = acl + "/auth_restricted.ttl";
308        final String auth2 = acl + "/auth_open.ttl";
309
310        when(mockNodeService.find(mockSession, acl)).thenReturn(mockAclResource);
311        when(mockProperty.getString()).thenReturn(acl);
312        when(mockAclResource.getPath()).thenReturn(acl);
313        when(mockResource.getPath()).thenReturn(accessTo);
314        when(mockResource.getTriples(anyObject(), eq(PropertiesRdfContext.class)))
315                .thenReturn(getResourceRdfStream(accessTo, acl));
316
317        when(mockAuthorizationResource1.getTypes()).thenReturn(Arrays.asList(WEBAC_AUTHORIZATION));
318        when(mockAuthorizationResource1.getPath()).thenReturn(auth1);
319        when(mockAuthorizationResource1.getTriples(anyObject(), eq(PropertiesRdfContext.class)))
320                .thenReturn(getRdfStreamFromResource(auth1, TTL));
321
322        when(mockAuthorizationResource2.getTypes()).thenReturn(Arrays.asList(WEBAC_AUTHORIZATION));
323        when(mockAuthorizationResource2.getPath()).thenReturn(auth2);
324        when(mockAuthorizationResource2.getTriples(anyObject(), eq(PropertiesRdfContext.class)))
325                .thenReturn(getRdfStreamFromResource(auth2, TTL));
326
327        when(mockAclResource.getChildren()).thenReturn(
328                Arrays.asList(mockAuthorizationResource1, mockAuthorizationResource2).iterator());
329
330        final Map<String, List<String>> roles = roleProvider.getRoles(mockNode, true);
331
332        assertEquals("There should be exactly one agent", 1, roles.size());
333        assertEquals("The agent should have one mode", 1, roles.get(agent).size());
334        assertTrue("The agent should be able to read", roles.get(agent).contains(WEBAC_MODE_READ_VALUE));
335    }
336
337    @Test
338    public void acl04Test() throws RepositoryException {
339        final String agent1 = "http://xmlns.com/foaf/0.1/Agent";
340        final String agent2 = "Editors";
341        final String accessTo = "/public_collection";
342        final String acl = "/acls/04";
343        final String auth1 = acl + "/auth1.ttl";
344        final String auth2 = acl + "/auth2.ttl";
345
346        when(mockNodeService.find(mockSession, acl)).thenReturn(mockAclResource);
347        when(mockProperty.getString()).thenReturn(acl);
348        when(mockAclResource.getPath()).thenReturn(acl);
349        when(mockResource.getPath()).thenReturn(accessTo);
350        when(mockResource.getTriples(anyObject(), eq(PropertiesRdfContext.class)))
351                .thenReturn(getResourceRdfStream(accessTo, acl));
352
353        when(mockAuthorizationResource1.getTypes()).thenReturn(Arrays.asList(WEBAC_AUTHORIZATION));
354        when(mockAuthorizationResource1.getPath()).thenReturn(auth1);
355        when(mockAuthorizationResource1.getTriples(anyObject(), eq(PropertiesRdfContext.class)))
356                .thenReturn(getRdfStreamFromResource(auth1, TTL));
357
358        when(mockAuthorizationResource2.getTypes()).thenReturn(Arrays.asList(WEBAC_AUTHORIZATION));
359        when(mockAuthorizationResource2.getPath()).thenReturn(auth2);
360        when(mockAuthorizationResource2.getTriples(anyObject(), eq(PropertiesRdfContext.class)))
361                .thenReturn(getRdfStreamFromResource(auth2, TTL));
362
363        when(mockAclResource.getChildren()).thenReturn(
364                Arrays.asList(mockAuthorizationResource1, mockAuthorizationResource2).iterator());
365
366        final Map<String, List<String>> roles = roleProvider.getRoles(mockNode, true);
367
368        assertEquals("There should be exactly two agents", 2, roles.size());
369        assertEquals("The agent should have one mode", 1, roles.get(agent1).size());
370        assertTrue("The agent should be able to read", roles.get(agent1).contains(WEBAC_MODE_READ_VALUE));
371        assertEquals("The agent should have two modes", 2, roles.get(agent2).size());
372        assertTrue("The agent should be able to read", roles.get(agent2).contains(WEBAC_MODE_READ_VALUE));
373        assertTrue("The agent should be able to write", roles.get(agent2).contains(WEBAC_MODE_READ_VALUE));
374    }
375
376    public void acl05Test() throws RepositoryException {
377        final String agent1 = "http://xmlns.com/foaf/0.1/Agent";
378        final String agent2 = "Admins";
379        final String accessTo = "/mixedCollection";
380        final String acl = "/acls/05";
381        final String auth1 = acl + "/auth_restricted.ttl";
382        final String auth2 = acl + "/auth_open.ttl";
383
384        when(mockNodeService.find(mockSession, acl)).thenReturn(mockAclResource);
385        when(mockProperty.getString()).thenReturn(acl);
386        when(mockAclResource.getPath()).thenReturn(acl);
387        when(mockResource.getPath()).thenReturn(accessTo);
388        when(mockResource.getTypes()).thenReturn(Arrays.asList(URI.create("http://example.com/terms#publicImage")));
389        when(mockResource.getTriples(anyObject(), eq(PropertiesRdfContext.class)))
390                .thenReturn(getResourceRdfStream(accessTo, acl));
391
392        when(mockAuthorizationResource1.getTypes()).thenReturn(Arrays.asList(WEBAC_AUTHORIZATION));
393        when(mockAuthorizationResource1.getPath()).thenReturn(auth1);
394        when(mockAuthorizationResource1.getTriples(anyObject(), eq(PropertiesRdfContext.class)))
395                .thenReturn(getRdfStreamFromResource(auth1, TTL));
396
397        when(mockAuthorizationResource2.getTypes()).thenReturn(Arrays.asList(WEBAC_AUTHORIZATION));
398        when(mockAuthorizationResource2.getPath()).thenReturn(auth2);
399        when(mockAuthorizationResource2.getTriples(anyObject(), eq(PropertiesRdfContext.class)))
400                .thenReturn(getRdfStreamFromResource(auth2, TTL));
401
402        when(mockAclResource.getChildren()).thenReturn(
403                Arrays.asList(mockAuthorizationResource1, mockAuthorizationResource2).iterator());
404
405        final Map<String, List<String>> roles = roleProvider.getRoles(mockNode, true);
406
407        assertEquals("There should be exactly two agents", 2, roles.size());
408        assertEquals("The agent should have one mode", 1, roles.get(agent1).size());
409        assertTrue("The agent should be able to read", roles.get(agent1).contains(WEBAC_MODE_READ_VALUE));
410        assertEquals("The agent should have one mode", 1, roles.get(agent2).size());
411        assertTrue("The agent should be able to read", roles.get(agent2).contains(WEBAC_MODE_READ_VALUE));
412    }
413
414    @Test
415    public void acl05Test2() throws RepositoryException {
416        final String agent1 = "http://xmlns.com/foaf/0.1/Agent";
417        final String accessTo = "/someOtherCollection";
418        final String acl = "/acls/05";
419        final String auth1 = acl + "/auth_restricted.ttl";
420        final String auth2 = acl + "/auth_open.ttl";
421
422        when(mockNodeService.find(mockSession, acl)).thenReturn(mockAclResource);
423        when(mockProperty.getString()).thenReturn(acl);
424        when(mockAclResource.getPath()).thenReturn(acl);
425        when(mockResource.getPath()).thenReturn(accessTo);
426        when(mockResource.getTypes()).thenReturn(Arrays.asList(URI.create("http://example.com/terms#publicImage")));
427        when(mockResource.getTriples(anyObject(), eq(PropertiesRdfContext.class)))
428                .thenReturn(getResourceRdfStream(accessTo, acl));
429
430        when(mockAuthorizationResource1.getTypes()).thenReturn(Arrays.asList(WEBAC_AUTHORIZATION));
431        when(mockAuthorizationResource1.getPath()).thenReturn(auth1);
432        when(mockAuthorizationResource1.getTriples(anyObject(), eq(PropertiesRdfContext.class)))
433                .thenReturn(getRdfStreamFromResource(auth1, TTL));
434
435        when(mockAuthorizationResource2.getTypes()).thenReturn(Arrays.asList(WEBAC_AUTHORIZATION));
436        when(mockAuthorizationResource2.getPath()).thenReturn(auth2);
437        when(mockAuthorizationResource2.getTriples(anyObject(), eq(PropertiesRdfContext.class)))
438                .thenReturn(getRdfStreamFromResource(auth2, TTL));
439
440        when(mockAclResource.getChildren()).thenReturn(
441                Arrays.asList(mockAuthorizationResource1, mockAuthorizationResource2).iterator());
442
443        final Map<String, List<String>> roles = roleProvider.getRoles(mockNode, true);
444
445        assertEquals("There should be exactly agent", 1, roles.size());
446        assertEquals("The agent should have one mode", 1, roles.get(agent1).size());
447        assertTrue("The agent should be able to read", roles.get(agent1).contains(WEBAC_MODE_READ_VALUE));
448    }
449
450    /* (non-Javadoc)
451     * Test that an in-repository resource used as a target for acl:agentClass has
452     * the rdf:type of foaf:Group. This test mocks a foaf:Group resource and should
453     * therefore retrieve two agents.
454     */
455    @Test
456    public void acl09Test1() throws RepositoryException {
457        final String agent1 = "person1";
458        final String agent2 = "person2";
459        final String accessTo = "/anotherCollection";
460
461        final String groupResource = "/group/foo";
462        final String acl = "/acls/09";
463        final String auth = acl + "/authorization.ttl";
464        final String group = acl + "/group.ttl";
465
466        when(mockNodeService.find(mockSession, acl)).thenReturn(mockAclResource);
467        when(mockNodeService.find(mockSession, groupResource)).thenReturn(mockAgentClassResource);
468        when(mockProperty.getString()).thenReturn(acl);
469        when(mockAclResource.getPath()).thenReturn(acl);
470        when(mockResource.getPath()).thenReturn(accessTo);
471        when(mockResource.getTypes()).thenReturn(new ArrayList<>());
472        when(mockResource.getTriples(anyObject(), eq(PropertiesRdfContext.class)))
473                .thenReturn(getResourceRdfStream(accessTo, acl));
474
475        when(mockAuthorizationResource1.getTypes()).thenReturn(Arrays.asList(WEBAC_AUTHORIZATION));
476        when(mockAuthorizationResource1.getPath()).thenReturn(auth);
477        when(mockAuthorizationResource1.getTriples(anyObject(), eq(PropertiesRdfContext.class)))
478                .thenReturn(getRdfStreamFromResource(auth, TTL));
479
480        when(mockAgentClassResource.getTypes()).thenReturn(Arrays.asList(FOAF_GROUP));
481        when(mockAgentClassResource.getPath()).thenReturn(groupResource);
482        when(mockAgentClassResource.getTriples(anyObject(), eq(PropertiesRdfContext.class)))
483                .thenReturn(getRdfStreamFromResource(group, TTL));
484
485        when(mockAclResource.getChildren()).thenReturn(
486                Arrays.asList(mockAuthorizationResource1).iterator());
487
488        final Map<String, List<String>> roles = roleProvider.getRoles(mockNode, true);
489
490        assertEquals("There should be exactly two agents", 2, roles.size());
491        assertEquals("The agent should have two modes", 2, roles.get(agent1).size());
492        assertTrue("The agent should be able to read", roles.get(agent1).contains(WEBAC_MODE_READ_VALUE));
493        assertTrue("The agent should be able to write", roles.get(agent1).contains(WEBAC_MODE_WRITE_VALUE));
494    }
495
496    /* (non-Javadoc)
497     * Test that an in-repository resource used as a target for acl:agentClass has
498     * the rdf:type of foaf:Group. This test mocks a resource that is not of the type
499     * foaf:Group and therefore should retrieve zero agents.
500     */
501    @Test
502    public void acl09Test2() throws RepositoryException {
503        final String agent1 = "person1";
504        final String agent2 = "person2";
505        final String accessTo = "/anotherCollection";
506
507        final String groupResource = "/group/foo";
508        final String acl = "/acls/09";
509        final String auth = acl + "/authorization.ttl";
510        final String group = acl + "/group.ttl";
511
512        when(mockNodeService.find(mockSession, acl)).thenReturn(mockAclResource);
513        when(mockNodeService.find(mockSession, groupResource)).thenReturn(mockAgentClassResource);
514        when(mockProperty.getString()).thenReturn(acl);
515        when(mockAclResource.getPath()).thenReturn(acl);
516        when(mockResource.getPath()).thenReturn(accessTo);
517        when(mockResource.getTypes()).thenReturn(new ArrayList<>());
518        when(mockResource.getTriples(anyObject(), eq(PropertiesRdfContext.class)))
519                .thenReturn(getResourceRdfStream(accessTo, acl));
520
521        when(mockAuthorizationResource1.getTypes()).thenReturn(Arrays.asList(WEBAC_AUTHORIZATION));
522        when(mockAuthorizationResource1.getPath()).thenReturn(auth);
523        when(mockAuthorizationResource1.getTriples(anyObject(), eq(PropertiesRdfContext.class)))
524                .thenReturn(getRdfStreamFromResource(auth, TTL));
525
526        when(mockAgentClassResource.getTypes()).thenReturn(new ArrayList<>());
527        when(mockAgentClassResource.getPath()).thenReturn(groupResource);
528        when(mockAgentClassResource.getTriples(anyObject(), eq(PropertiesRdfContext.class)))
529                .thenReturn(getRdfStreamFromResource(group, TTL));
530
531        when(mockAclResource.getChildren()).thenReturn(
532                Arrays.asList(mockAuthorizationResource1).iterator());
533
534        final Map<String, List<String>> roles = roleProvider.getRoles(mockNode, true);
535
536        assertEquals("There should be exactly zero agents", 0, roles.size());
537    }
538
539    @Test
540    public void noAclTest1() throws RepositoryException {
541        final String agent1 = "http://xmlns.com/foaf/0.1/Agent";
542
543        when(mockResource.getTriples(anyObject(), eq(PropertiesRdfContext.class))).thenReturn(new RdfStream());
544        when(mockResource.getPath()).thenReturn("/");
545        when(mockResource.getTypes()).thenReturn(
546                Arrays.asList(URI.create(REPOSITORY_NAMESPACE + "Resource")));
547        final Map<String, List<String>> roles = roleProvider.getRoles(mockNode, true);
548
549        assertEquals("There should be exactly one agent", 1, roles.size());
550        assertEquals("The agent should have zero modes", 0, roles.get(agent1).size());
551    }
552
553    @Test
554    public void noAclTestMalformedRdf2() throws RepositoryException {
555        final String agent1 = "http://xmlns.com/foaf/0.1/Agent";
556
557        when(mockResource.getTriples(anyObject(), eq(PropertiesRdfContext.class))).thenReturn(new RdfStream());
558        when(mockResource.getTriples(anyObject(), eq(PropertiesRdfContext.class))).thenReturn(new RdfStream());
559        when(mockResource.getPath()).thenReturn("/");
560        when(mockResource.getTypes()).thenReturn(
561                Arrays.asList(URI.create(REPOSITORY_NAMESPACE + "Resource")));
562
563        System.setProperty(ROOT_AUTHORIZATION_PROPERTY, "./target/test-classes/logback-test.xml");
564        final Map<String, List<String>> roles = roleProvider.getRoles(mockNode, true);
565        System.clearProperty(ROOT_AUTHORIZATION_PROPERTY);
566
567        assertEquals("There should be exactly one agent", 1, roles.size());
568        assertEquals("The agent should have zero modes", 0, roles.get(agent1).size());
569    }
570
571    @Test
572    public void noAclTestOkRdf3() throws RepositoryException {
573        final String agent1 = "testAdminUser";
574
575        when(mockResource.getTriples(anyObject(), eq(PropertiesRdfContext.class))).thenReturn(new RdfStream());
576        when(mockResource.getPath()).thenReturn("/");
577        when(mockResource.getTypes()).thenReturn(
578                Arrays.asList(URI.create(REPOSITORY_NAMESPACE + "Resource")));
579
580        System.setProperty(ROOT_AUTHORIZATION_PROPERTY, "./target/test-classes/test-root-authorization.ttl");
581        final Map<String, List<String>> roles = roleProvider.getRoles(mockNode, true);
582        System.clearProperty(ROOT_AUTHORIZATION_PROPERTY);
583
584        assertEquals("There should be exactly one agent", 1, roles.size());
585        assertEquals("The agent should have one mode", 1, roles.get(agent1).size());
586        assertTrue("The agent should be able to read", roles.get(agent1).contains(WEBAC_MODE_READ_VALUE));
587    }
588
589    private static RdfStream getRdfStreamFromResource(final String resourcePath, final Lang lang) {
590        final Model model = createDefaultModel();
591
592        RDFDataMgr.read(model, WebACRolesProviderTest.class.getResourceAsStream(resourcePath), lang);
593
594        final List<Triple> triples = new ArrayList<>();
595        model.listStatements().forEachRemaining(x -> {
596            final Triple t = x.asTriple();
597            if (t.getObject().isURI() && t.getObject().getURI().startsWith(FEDORA_URI_PREFIX)) {
598                triples.add(new Triple(t.getSubject(), t.getPredicate(),
599                        createURI(FEDORA_PREFIX + t.getObject().getURI().substring(FEDORA_URI_PREFIX.length()))));
600            } else {
601                triples.add(t);
602            }
603        });
604
605        return new RdfStream(triples);
606    }
607
608    private RdfStream getResourceRdfStream(final String subject, final String aclTarget) {
609        return new RdfStream(Arrays.asList(
610                    new Triple(createURI(FEDORA_PREFIX + subject),
611                               createURI(WEBAC_ACCESS_CONTROL_VALUE),
612                               createURI(FEDORA_PREFIX + aclTarget))
613                ));
614    }
615}