You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by an...@apache.org on 2018/11/17 17:20:46 UTC
[20/34] jena git commit: JENA-1623: Server authorization by HTTP
authentication.
JENA-1623: Server authorization by HTTP authentication.
Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/fcbcc78e
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/fcbcc78e
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/fcbcc78e
Branch: refs/heads/master
Commit: fcbcc78e9be8f4eb04fab3207b61bc54ccb48fad
Parents: 6e8e074
Author: Andy Seaborne <an...@apache.org>
Authored: Sat Nov 3 16:57:13 2018 +0000
Committer: Andy Seaborne <an...@apache.org>
Committed: Tue Nov 13 15:39:14 2018 +0000
----------------------------------------------------------------------
.../AbstractTestGraphSecurityAssembler.java | 326 +++++++++++++++++++
.../access/AbstractTestSecurityAssembler.java | 326 -------------------
.../fuseki/access/TS_SecurityFiltering.java | 13 +-
.../fuseki/access/TestAssemblerSeparate.java | 26 --
.../jena/fuseki/access/TestAssemblerShared.java | 26 --
.../fuseki/access/TestAuthorizedRequest.java | 111 +++++++
.../TestGraphSecurityAssemblerSeparate.java | 26 ++
.../TestGraphSecurityAssemblerShared.java | 26 ++
.../jena/fuseki/access/TestPasswordAccess.java | 230 -------------
.../jena/fuseki/access/TestPasswordServer.java | 217 ++++++++++++
.../fuseki/access/TestPasswordServices.java | 230 +++++++++++++
.../access/TestSecurityAssemblerBuild.java | 1 +
.../testing/Access/allowedUsers.ttl | 15 +
.../testing/Access/assem-security.ttl | 2 +-
.../testing/Access/config-server-1.ttl | 43 +++
.../testing/Access/config-server-2.ttl | 43 +++
.../jena-fuseki-access/testing/Access/passwd | 3 +
.../jena/fuseki/build/FusekiBuildLib.java | 4 +-
.../apache/jena/fuseki/build/FusekiBuilder.java | 41 +++
.../apache/jena/fuseki/build/FusekiConfig.java | 83 ++---
.../jena/fuseki/build/RefCountingMap.java | 185 -----------
.../jena/fuseki/build/RequestAuthorization.java | 115 +++++++
.../apache/jena/fuseki/server/DataService.java | 7 +-
.../jena/fuseki/servlets/ActionService.java | 7 +-
.../apache/jena/fuseki/servlets/AuthFilter.java | 75 +++++
.../jena/fuseki/servlets/FusekiFilter.java | 4 +-
.../org/apache/jena/fuseki/main/FusekiLib.java | 7 -
.../apache/jena/fuseki/main/FusekiServer.java | 28 +-
.../apache/jena/fuseki/main/FusekiTestAuth.java | 4 +-
.../jena/fuseki/main/TestFusekiTestAuth.java | 4 +-
30 files changed, 1367 insertions(+), 861 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jena/blob/fcbcc78e/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/AbstractTestGraphSecurityAssembler.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/AbstractTestGraphSecurityAssembler.java b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/AbstractTestGraphSecurityAssembler.java
new file mode 100644
index 0000000..1335702
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/AbstractTestGraphSecurityAssembler.java
@@ -0,0 +1,326 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.fuseki.access;
+
+import static org.apache.jena.fuseki.access.AccessTestLib.assertSeen;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.apache.jena.atlas.iterator.Iter;
+import org.apache.jena.atlas.lib.SetUtils;
+import org.apache.jena.atlas.lib.StrUtils;
+import org.apache.jena.atlas.web.HttpException;
+import org.apache.jena.fuseki.main.FusekiServer;
+import org.apache.jena.fuseki.system.FusekiNetLib;
+import org.apache.jena.graph.Node;
+import org.apache.jena.query.Dataset;
+import org.apache.jena.query.QuerySolution;
+import org.apache.jena.rdf.model.Model;
+import org.apache.jena.rdf.model.RDFNode;
+import org.apache.jena.rdf.model.Resource;
+import org.apache.jena.rdfconnection.RDFConnection;
+import org.apache.jena.rdfconnection.RDFConnectionFactory;
+import org.apache.jena.sparql.core.DatasetGraph;
+import org.apache.jena.sparql.core.Quad;
+import org.apache.jena.sparql.sse.SSE;
+import org.apache.jena.sys.JenaSystem;
+import org.apache.jena.system.Txn;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Test on the assembler for data access control.
+ * <ul>
+ * <li>assem-security.ttl - two services "/database" and "/plain" each with their own dataset.
+ * <li>assem-security-shared.ttl - two services "/database" and "/plain" with a shared dataset.
+ * </ul>
+ *
+ * @see TestSecurityFilterFuseki TestSecurityFilterFuseki for other HTTP tests.
+ */
+
+public abstract class AbstractTestGraphSecurityAssembler {
+ static { JenaSystem.init(); }
+ static final String DIR = "testing/Access/";
+
+// @Parameters(name = "{index}: {0}")
+// public static Iterable<Object[]> data() {
+// Object[] obj1 = { DIR+"assem-security.ttl" , false };
+// Object[] obj2 = { DIR+"assem-security-shared.ttl" , true };
+// return Arrays.asList(obj1, obj2);
+// }
+
+ private final String assemblerFile;
+ private static AtomicReference<String> user = new AtomicReference<>();
+
+ private boolean sharedDatabase;
+
+ // Parameterized tests don't provide a convenient way to run code at the start and end of each parameter run and access the parameters.
+ private static FusekiServer server;
+ private FusekiServer getServer() {
+ if ( server == null )
+ server = setup(assemblerFile, false);
+ return server;
+ }
+ @AfterClass public static void afterClass() {
+ server.stop();
+ server = null;
+ user.set(null);
+ }
+
+ @Before
+ public void before() {
+ user.set(null);
+ }
+
+ private String getURL() {
+ getServer();
+ int port = server.getPort();
+ return "http://localhost:"+port+"/database";
+ }
+
+ private static FusekiServer setup(String assembler, boolean sharedDatabase) {
+ int port = FusekiNetLib.choosePort();
+ FusekiServer server = DataAccessCtl.fusekiBuilder((a)->user.get())
+ .port(port)
+ .parseConfigFile(assembler)
+ .build();
+ server.start();
+
+ if ( sharedDatabase ) {
+ String data = StrUtils.strjoinNL
+ ("PREFIX : <http://example/>"
+ ,"INSERT DATA {"
+ ," :s0 :p :o ."
+ ," GRAPH <http://host/graphname1> {:s1 :p :o}"
+ ," GRAPH <http://host/graphname3> {:s3 :p :o}"
+ ," GRAPH <http://host/graphname9> {:s9 :p :o}"
+ ,"}"
+ );
+ String plainUrl = "http://localhost:"+server.getPort()+"/plain";
+ try(RDFConnection conn = RDFConnectionFactory.connect(plainUrl)) {
+ conn.update(data);
+ }
+ } else {
+ DatasetGraph dsg = server.getDataAccessPointRegistry().get("/database").getDataService().getDataset();
+ Txn.executeWrite(dsg, ()->{
+ dsg.add(SSE.parseQuad("(<http://host/graphname1> :s1 :p :o)"));
+ dsg.add(SSE.parseQuad("(<http://host/graphname3> :s3 :p :o)"));
+ dsg.add(SSE.parseQuad("(<http://host/graphname9> :s9 :p :o)"));
+ });
+ }
+ return server;
+ }
+
+ protected AbstractTestGraphSecurityAssembler(String assemberFile, boolean sharedDatabase) {
+ this.assemblerFile = assemberFile;
+ this.sharedDatabase = sharedDatabase ;
+ }
+
+ private static Node s1 = SSE.parseNode(":s1");
+ private static Node s2 = SSE.parseNode(":s2");
+ private static Node s3 = SSE.parseNode(":s3");
+ private static Node s9 = SSE.parseNode(":s9");
+
+ // The access controlled dataset.
+
+// { SecurityRegistry
+// user1 -> dft:false / [http://host/graphname2, http://host/graphname1, http://host/graphname3]
+// user2 -> dft:false / [http://host/graphname9]
+// userZ -> dft:false / [http://host/graphnameZ]
+// user3 -> dft:false / [http://host/graphname4, http://host/graphname3, http://host/graphname5]
+// }
+
+
+ @Test public void query_user1() {
+ user.set("user1");
+ try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
+ Set<Node> visible = query(conn, "SELECT * { GRAPH ?g { ?s ?p ?o }}");
+ assertSeen(visible, s1, s3);
+ }
+ }
+
+ @Test public void query_userX() {
+ user.set("userX"); // No such user in the registry
+ try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
+ Set<Node> visible = query(conn, "SELECT * { GRAPH ?g { ?s ?p ?o }}");
+ assertSeen(visible);
+ }
+ }
+
+ @Test public void query_no_user() {
+ user.set(null); // No user.
+ try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
+ Set<Node> visible = query(conn, "SELECT * { GRAPH ?g { ?s ?p ?o }}");
+ assertSeen(visible);
+ }
+ }
+
+ @Test public void query_user2() {
+ user.set("user2");
+ try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
+ Set<Node> visible = query(conn, "SELECT * { GRAPH ?g { ?s ?p ?o }}");
+ assertSeen(visible, s9);
+ }
+ }
+
+ @Test public void query_userZ() {
+ user.set("userZ"); // No graphs with data.
+ try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
+ Set<Node> visible = query(conn, "SELECT * { GRAPH ?g { ?s ?p ?o }}");
+ assertSeen(visible);
+ }
+ }
+
+ // GSP. "http://host/graphname1"
+ @Test public void gsp_dft_user1() {
+ user.set("user1");
+ try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
+ Set<Node> visible = gsp(conn, null);
+ assertSeen(visible);
+ }
+ }
+
+ @Test public void gsp_ng_user1() {
+ user.set("user1");
+ try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
+ Set<Node> visible = gsp(conn, "http://host/graphname1");
+ assertSeen(visible, s1);
+ }
+ }
+
+ @Test public void gsp_dft_user2() {
+ user.set("user2");
+ try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
+ gsp404(conn, null);
+ }
+ }
+
+ @Test public void gsp_ng_user2() {
+ user.set("user2");
+ try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
+ gsp404(conn, "http://host/graphname1");
+ }
+ }
+
+ @Test public void gsp_dft_userX() {
+ user.set("userX");
+ try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
+ gsp404(conn, null);
+ }
+ }
+
+ @Test public void gsp_ng_userX() {
+ user.set("userX");
+ try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
+ gsp404(conn, "http://host/graphname1");
+ }
+ }
+
+ @Test public void gsp_dft_user_null() {
+ user.set(null);
+ try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
+ gsp404(conn, null);
+ }
+ }
+
+ @Test public void gsp_ng_user_null() {
+ try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
+ gsp404(conn, "http://host/graphname1");
+ }
+ }
+
+// // Quads
+// user.set("user1");
+// try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
+// Set<Node> visible = dataset(conn);
+// assertSeen(visible, s1, s3);
+// }
+// user.set("user2");
+// try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
+// Set<Node> visible = dataset(conn);
+// assertSeen(visible, s9);
+// }
+// user.set("userX");
+// try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
+// Set<Node> visible = dataset(conn);
+// assertSeen(visible);
+// }
+// user.set(null);
+// try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
+// Set<Node> visible = dataset(conn);
+// assertSeen(visible);
+// }
+
+
+ private Set<Node> gsp(RDFConnection conn, String graphName) {
+ Set<Node> results = new HashSet<>();
+ Model model = graphName == null ? conn.fetch() : conn.fetch(graphName);
+ // Extract subjects.
+ Set<Node> seen =
+ SetUtils.toSet(
+ Iter.asStream(model.listSubjects())
+ .map(Resource::asNode)
+ );
+ return seen;
+ }
+
+ private void gsp404(RDFConnection conn, String graphName) {
+ gspHttp(conn, 404, graphName);
+ }
+
+ private void gspHttp(RDFConnection conn, int statusCode, String graphName) {
+ try {
+ gsp(conn, graphName);
+ if ( statusCode < 200 && statusCode > 299 )
+ fail("Should have responded with "+statusCode);
+ } catch (HttpException ex) {
+ assertEquals(statusCode, ex.getResponseCode());
+ }
+ }
+
+ private Set<Node> dataset(RDFConnection conn) {
+ Dataset ds = conn.fetchDataset();
+ Set<Node> seen =
+ SetUtils.toSet(
+ Iter.asStream(ds.asDatasetGraph().find())
+ .map(Quad::getSubject)
+ );
+ return seen;
+ }
+
+ private Set<Node> query(RDFConnection conn, String queryString) {
+ Set<Node> results = new HashSet<>();
+ conn.queryResultSet(queryString, rs->{
+ List<QuerySolution> list = Iter.toList(rs);
+ list.stream()
+ .map(qs->qs.get("s"))
+ .filter(Objects::nonNull)
+ .map(RDFNode::asNode)
+ .forEach(n->results.add(n));
+ });
+ return results;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/fcbcc78e/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/AbstractTestSecurityAssembler.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/AbstractTestSecurityAssembler.java b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/AbstractTestSecurityAssembler.java
deleted file mode 100644
index a7e5ac1..0000000
--- a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/AbstractTestSecurityAssembler.java
+++ /dev/null
@@ -1,326 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.jena.fuseki.access;
-
-import static org.apache.jena.fuseki.access.AccessTestLib.assertSeen;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
-import java.util.HashSet;
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicReference;
-
-import org.apache.jena.atlas.iterator.Iter;
-import org.apache.jena.atlas.lib.SetUtils;
-import org.apache.jena.atlas.lib.StrUtils;
-import org.apache.jena.atlas.web.HttpException;
-import org.apache.jena.fuseki.main.FusekiServer;
-import org.apache.jena.fuseki.system.FusekiNetLib;
-import org.apache.jena.graph.Node;
-import org.apache.jena.query.Dataset;
-import org.apache.jena.query.QuerySolution;
-import org.apache.jena.rdf.model.Model;
-import org.apache.jena.rdf.model.RDFNode;
-import org.apache.jena.rdf.model.Resource;
-import org.apache.jena.rdfconnection.RDFConnection;
-import org.apache.jena.rdfconnection.RDFConnectionFactory;
-import org.apache.jena.sparql.core.DatasetGraph;
-import org.apache.jena.sparql.core.Quad;
-import org.apache.jena.sparql.sse.SSE;
-import org.apache.jena.sys.JenaSystem;
-import org.apache.jena.system.Txn;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * Test on the assembler for data access control.
- * <ul>
- * <li>assem-security.ttl - two services "/database" and "/plain" each with their own dataset.
- * <li>assem-security-shared.ttl - two services "/database" and "/plain" with a shared dataset.
- * </ul>
- *
- * @see TestSecurityFilterFuseki TestSecurityFilterFuseki for other HTTP tests.
- */
-
-public abstract class AbstractTestSecurityAssembler {
- static { JenaSystem.init(); }
- static final String DIR = "testing/Access/";
-
-// @Parameters(name = "{index}: {0}")
-// public static Iterable<Object[]> data() {
-// Object[] obj1 = { DIR+"assem-security.ttl" , false };
-// Object[] obj2 = { DIR+"assem-security-shared.ttl" , true };
-// return Arrays.asList(obj1, obj2);
-// }
-
- private final String assemblerFile;
- private static AtomicReference<String> user = new AtomicReference<>();
-
- private boolean sharedDatabase;
-
- // Parameterized tests don't provide a convenient way to run code at the start and end of each parameter run and access the parameters.
- private static FusekiServer server;
- private FusekiServer getServer() {
- if ( server == null )
- server = setup(assemblerFile, false);
- return server;
- }
- @AfterClass public static void afterClass() {
- server.stop();
- server = null;
- user.set(null);
- }
-
- @Before
- public void before() {
- user.set(null);
- }
-
- private String getURL() {
- getServer();
- int port = server.getPort();
- return "http://localhost:"+port+"/database";
- }
-
- private static FusekiServer setup(String assembler, boolean sharedDatabase) {
- int port = FusekiNetLib.choosePort();
- FusekiServer server = DataAccessCtl.fusekiBuilder((a)->user.get())
- .port(port)
- .parseConfigFile(assembler)
- .build();
- server.start();
-
- if ( sharedDatabase ) {
- String data = StrUtils.strjoinNL
- ("PREFIX : <http://example/>"
- ,"INSERT DATA {"
- ," :s0 :p :o ."
- ," GRAPH <http://host/graphname1> {:s1 :p :o}"
- ," GRAPH <http://host/graphname3> {:s3 :p :o}"
- ," GRAPH <http://host/graphname9> {:s9 :p :o}"
- ,"}"
- );
- String plainUrl = "http://localhost:"+server.getPort()+"/plain";
- try(RDFConnection conn = RDFConnectionFactory.connect(plainUrl)) {
- conn.update(data);
- }
- } else {
- DatasetGraph dsg = server.getDataAccessPointRegistry().get("/database").getDataService().getDataset();
- Txn.executeWrite(dsg, ()->{
- dsg.add(SSE.parseQuad("(<http://host/graphname1> :s1 :p :o)"));
- dsg.add(SSE.parseQuad("(<http://host/graphname3> :s3 :p :o)"));
- dsg.add(SSE.parseQuad("(<http://host/graphname9> :s9 :p :o)"));
- });
- }
- return server;
- }
-
- protected AbstractTestSecurityAssembler(String assemberFile, boolean sharedDatabase) {
- this.assemblerFile = assemberFile;
- this.sharedDatabase = sharedDatabase ;
- }
-
- private static Node s1 = SSE.parseNode(":s1");
- private static Node s2 = SSE.parseNode(":s2");
- private static Node s3 = SSE.parseNode(":s3");
- private static Node s9 = SSE.parseNode(":s9");
-
- // The access controlled dataset.
-
-// { SecurityRegistry
-// user1 -> dft:false / [http://host/graphname2, http://host/graphname1, http://host/graphname3]
-// user2 -> dft:false / [http://host/graphname9]
-// userZ -> dft:false / [http://host/graphnameZ]
-// user3 -> dft:false / [http://host/graphname4, http://host/graphname3, http://host/graphname5]
-// }
-
-
- @Test public void query_user1() {
- user.set("user1");
- try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
- Set<Node> visible = query(conn, "SELECT * { GRAPH ?g { ?s ?p ?o }}");
- assertSeen(visible, s1, s3);
- }
- }
-
- @Test public void query_userX() {
- user.set("userX"); // No such user in the registry
- try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
- Set<Node> visible = query(conn, "SELECT * { GRAPH ?g { ?s ?p ?o }}");
- assertSeen(visible);
- }
- }
-
- @Test public void query_no_user() {
- user.set(null); // No user.
- try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
- Set<Node> visible = query(conn, "SELECT * { GRAPH ?g { ?s ?p ?o }}");
- assertSeen(visible);
- }
- }
-
- @Test public void query_user2() {
- user.set("user2");
- try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
- Set<Node> visible = query(conn, "SELECT * { GRAPH ?g { ?s ?p ?o }}");
- assertSeen(visible, s9);
- }
- }
-
- @Test public void query_userZ() {
- user.set("userZ"); // No graphs with data.
- try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
- Set<Node> visible = query(conn, "SELECT * { GRAPH ?g { ?s ?p ?o }}");
- assertSeen(visible);
- }
- }
-
- // GSP. "http://host/graphname1"
- @Test public void gsp_dft_user1() {
- user.set("user1");
- try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
- Set<Node> visible = gsp(conn, null);
- assertSeen(visible);
- }
- }
-
- @Test public void gsp_ng_user1() {
- user.set("user1");
- try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
- Set<Node> visible = gsp(conn, "http://host/graphname1");
- assertSeen(visible, s1);
- }
- }
-
- @Test public void gsp_dft_user2() {
- user.set("user2");
- try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
- gsp404(conn, null);
- }
- }
-
- @Test public void gsp_ng_user2() {
- user.set("user2");
- try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
- gsp404(conn, "http://host/graphname1");
- }
- }
-
- @Test public void gsp_dft_userX() {
- user.set("userX");
- try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
- gsp404(conn, null);
- }
- }
-
- @Test public void gsp_ng_userX() {
- user.set("userX");
- try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
- gsp404(conn, "http://host/graphname1");
- }
- }
-
- @Test public void gsp_dft_user_null() {
- user.set(null);
- try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
- gsp404(conn, null);
- }
- }
-
- @Test public void gsp_ng_user_null() {
- try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
- gsp404(conn, "http://host/graphname1");
- }
- }
-
-// // Quads
-// user.set("user1");
-// try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
-// Set<Node> visible = dataset(conn);
-// assertSeen(visible, s1, s3);
-// }
-// user.set("user2");
-// try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
-// Set<Node> visible = dataset(conn);
-// assertSeen(visible, s9);
-// }
-// user.set("userX");
-// try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
-// Set<Node> visible = dataset(conn);
-// assertSeen(visible);
-// }
-// user.set(null);
-// try(RDFConnection conn = RDFConnectionFactory.connect(getURL())) {
-// Set<Node> visible = dataset(conn);
-// assertSeen(visible);
-// }
-
-
- private Set<Node> gsp(RDFConnection conn, String graphName) {
- Set<Node> results = new HashSet<>();
- Model model = graphName == null ? conn.fetch() : conn.fetch(graphName);
- // Extract subjects.
- Set<Node> seen =
- SetUtils.toSet(
- Iter.asStream(model.listSubjects())
- .map(Resource::asNode)
- );
- return seen;
- }
-
- private void gsp404(RDFConnection conn, String graphName) {
- gspHttp(conn, 404, graphName);
- }
-
- private void gspHttp(RDFConnection conn, int statusCode, String graphName) {
- try {
- gsp(conn, graphName);
- if ( statusCode < 200 && statusCode > 299 )
- fail("Should have responded with "+statusCode);
- } catch (HttpException ex) {
- assertEquals(statusCode, ex.getResponseCode());
- }
- }
-
- private Set<Node> dataset(RDFConnection conn) {
- Dataset ds = conn.fetchDataset();
- Set<Node> seen =
- SetUtils.toSet(
- Iter.asStream(ds.asDatasetGraph().find())
- .map(Quad::getSubject)
- );
- return seen;
- }
-
- private Set<Node> query(RDFConnection conn, String queryString) {
- Set<Node> results = new HashSet<>();
- conn.queryResultSet(queryString, rs->{
- List<QuerySolution> list = Iter.toList(rs);
- list.stream()
- .map(qs->qs.get("s"))
- .filter(Objects::nonNull)
- .map(RDFNode::asNode)
- .forEach(n->results.add(n));
- });
- return results;
- }
-}
http://git-wip-us.apache.org/repos/asf/jena/blob/fcbcc78e/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TS_SecurityFiltering.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TS_SecurityFiltering.java b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TS_SecurityFiltering.java
index 3face49..19987f8 100644
--- a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TS_SecurityFiltering.java
+++ b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TS_SecurityFiltering.java
@@ -26,12 +26,17 @@ import org.junit.runners.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses( {
- TestSecurityFilterLocal.class
+ TestAuthorizedRequest.class
+
+ , TestSecurityFilterLocal.class
, TestSecurityFilterFuseki.class
+
, TestSecurityAssemblerBuild.class
- , TestAssemblerSeparate.class
- , TestAssemblerShared.class
- , TestPasswordAccess.class
+ , TestGraphSecurityAssemblerSeparate.class
+ , TestGraphSecurityAssemblerShared.class
+
+ , TestPasswordServer.class
+ , TestPasswordServices.class
})
public class TS_SecurityFiltering {
http://git-wip-us.apache.org/repos/asf/jena/blob/fcbcc78e/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestAssemblerSeparate.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestAssemblerSeparate.java b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestAssemblerSeparate.java
deleted file mode 100644
index 78281f1..0000000
--- a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestAssemblerSeparate.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.jena.fuseki.access;
-
-public class TestAssemblerSeparate extends AbstractTestSecurityAssembler {
-
- public TestAssemblerSeparate() {
- super(DIR+"assem-security.ttl", false);
- }
-}
http://git-wip-us.apache.org/repos/asf/jena/blob/fcbcc78e/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestAssemblerShared.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestAssemblerShared.java b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestAssemblerShared.java
deleted file mode 100644
index 32d182b..0000000
--- a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestAssemblerShared.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.jena.fuseki.access;
-
-public class TestAssemblerShared extends AbstractTestSecurityAssembler {
-
- public TestAssemblerShared() {
- super(DIR+"assem-security-shared.ttl", true);
- }
-}
http://git-wip-us.apache.org/repos/asf/jena/blob/fcbcc78e/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestAuthorizedRequest.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestAuthorizedRequest.java b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestAuthorizedRequest.java
new file mode 100644
index 0000000..480708f
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestAuthorizedRequest.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.fuseki.access;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.jena.fuseki.build.FusekiBuilder;
+import org.apache.jena.fuseki.build.RequestAuthorization;
+import org.apache.jena.rdf.model.Model;
+import org.apache.jena.rdf.model.Resource;
+import org.apache.jena.riot.RDFDataMgr;
+import org.junit.Test;
+
+public class TestAuthorizedRequest {
+
+ static Model model = RDFDataMgr.loadModel("testing/Access/allowedUsers.ttl");
+
+
+ @Test public void authrequest_anon() {
+ RequestAuthorization req = RequestAuthorization.policyAllowAnon();
+ assertTrue(req.isAllowed(null));
+ assertTrue(req.isAllowed("user1"));
+ }
+
+ @Test public void authrequest_anyLoggedIn_1() {
+ RequestAuthorization req = RequestAuthorization.policyAllowAuthenticated();
+ assertFalse(req.isAllowed(null));
+ assertTrue(req.isAllowed("user1"));
+ }
+
+ @Test public void authrequest_anyLoggedIn_2() {
+ RequestAuthorization req = RequestAuthorization.policyAllowSpecific("*");
+ assertFalse(req.isAllowed(null));
+ assertTrue(req.isAllowed("user1"));
+ }
+
+ @Test public void authrequest_noOne() {
+ RequestAuthorization req = RequestAuthorization.policyNoAccess();
+ assertFalse(req.isAllowed(null));
+ assertFalse(req.isAllowed("user1"));
+ }
+
+
+ @Test public void authrequest_user_1() {
+ RequestAuthorization req = RequestAuthorization.policyAllowSpecific("user1", "user2");
+ assertFalse(req.isAllowed(null));
+ assertTrue(req.isAllowed("user1"));
+ assertTrue(req.isAllowed("user2"));
+ assertFalse(req.isAllowed("user3"));
+ }
+
+ @Test public void authrequest_parse_no_info_1() {
+ Resource r = model.createResource("http://example/notInData");
+ RequestAuthorization req = FusekiBuilder.allowedUsers(r);
+ assertNull(req);
+ }
+
+ @Test public void authrequest_parse_no_info_2() {
+ Resource r = model.createResource("http://example/none");
+ RequestAuthorization req = FusekiBuilder.allowedUsers(r);
+ assertNull(req);
+ }
+
+ @Test public void authrequest_parse_1() {
+ Resource r = model.createResource("http://example/r1");
+ RequestAuthorization req = FusekiBuilder.allowedUsers(r);
+ assertNotNull(req);
+ assertFalse(req.isAllowed(null));
+ assertTrue(req.isAllowed("user1"));
+ assertTrue(req.isAllowed("user2"));
+ assertFalse(req.isAllowed("user3"));
+ }
+
+ @Test public void authrequest_parse_2() {
+ Resource r = model.createResource("http://example/r2");
+ RequestAuthorization req = FusekiBuilder.allowedUsers(r);
+ assertNotNull(req);
+ assertFalse(req.isAllowed(null));
+ assertTrue(req.isAllowed("user1"));
+ assertTrue(req.isAllowed("user2"));
+ assertFalse(req.isAllowed("user3"));
+ }
+
+ @Test public void authrequest_parse_loggedIn() {
+ Resource r = model.createResource("http://example/rLoggedIn");
+ RequestAuthorization req = FusekiBuilder.allowedUsers(r);
+ assertNotNull(req);
+ assertFalse(req.isAllowed(null));
+ assertTrue(req.isAllowed("user1"));
+ assertTrue(req.isAllowed("user3"));
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/fcbcc78e/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestGraphSecurityAssemblerSeparate.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestGraphSecurityAssemblerSeparate.java b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestGraphSecurityAssemblerSeparate.java
new file mode 100644
index 0000000..dbf0456
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestGraphSecurityAssemblerSeparate.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.fuseki.access;
+
+public class TestGraphSecurityAssemblerSeparate extends AbstractTestGraphSecurityAssembler {
+
+ public TestGraphSecurityAssemblerSeparate() {
+ super(DIR+"assem-security.ttl", false);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/fcbcc78e/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestGraphSecurityAssemblerShared.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestGraphSecurityAssemblerShared.java b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestGraphSecurityAssemblerShared.java
new file mode 100644
index 0000000..0f55302
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestGraphSecurityAssemblerShared.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.fuseki.access;
+
+public class TestGraphSecurityAssemblerShared extends AbstractTestGraphSecurityAssembler {
+
+ public TestGraphSecurityAssemblerShared() {
+ super(DIR+"assem-security-shared.ttl", true);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/fcbcc78e/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestPasswordAccess.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestPasswordAccess.java b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestPasswordAccess.java
deleted file mode 100644
index d81de8c..0000000
--- a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestPasswordAccess.java
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.jena.fuseki.access;
-
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.fail;
-import static org.junit.Assume.assumeFalse;
-
-import java.util.Arrays;
-
-import org.apache.http.client.HttpClient;
-import org.apache.jena.atlas.logging.LogCtl;
-import org.apache.jena.atlas.web.HttpException;
-import org.apache.jena.atlas.web.TypedInputStream;
-import org.apache.jena.atlas.web.WebLib;
-import org.apache.jena.fuseki.build.FusekiBuilder;
-import org.apache.jena.fuseki.jetty.JettyLib;
-import org.apache.jena.fuseki.main.FusekiServer;
-import org.apache.jena.fuseki.server.DataService;
-import org.apache.jena.query.DatasetFactory;
-import org.apache.jena.riot.web.HttpCaptureResponse;
-import org.apache.jena.riot.web.HttpOp;
-import org.apache.jena.riot.web.HttpOp.CaptureInput;
-import org.apache.jena.sparql.core.DatasetGraphFactory;
-import org.apache.jena.web.HttpSC;
-import org.eclipse.jetty.security.ConstraintSecurityHandler;
-import org.eclipse.jetty.security.UserStore;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-/** Tests for password access to a server and to services. */
-public class TestPasswordAccess {
-
- private static FusekiServer fusekiServer = null;
- private static int port = WebLib.choosePort();
- private static String serverURL = "http://localhost:"+port+"/";
- private static AuthSetup authSetup1 = new AuthSetup("localhost", port, "user1", "pw1", "TripleStore");
- private static AuthSetup authSetup2 = new AuthSetup("localhost", port, "user2", "pw2", "TripleStore");
- // Not in the user store.
- private static AuthSetup authSetupX = new AuthSetup("localhost", port, "userX", "pwX", "TripleStore");
-
- // All users must log in to access any resource. Disables some "open" tests.
- private static boolean ConstraintServer = true;
-
- @BeforeClass
- public static void beforeClass() {
- if ( false )
- // To watch the HTTP headers
- LogCtl.enable("org.apache.http.headers");
-
- // Two authorized users.
- UserStore userStore = new UserStore();
- JettyLib.addUser(userStore, authSetup1.user, authSetup1.password);
- JettyLib.addUser(userStore, authSetup2.user, authSetup2.password);
- try { userStore.start(); }
- catch (Exception ex) { throw new RuntimeException("UserStore", ex); }
-
- ConstraintSecurityHandler sh = JettyLib.makeSecurityHandler(authSetup1.realm, userStore);
-
- // Secure these areas.
- JettyLib.addPathConstraint(sh, "/ds");
- // Allow auth control even through there isn't anything there
- JettyLib.addPathConstraint(sh, "/nowhere");
-
- JettyLib.addPathConstraint(sh, "/ctl");
- // Not controlled: JettyLib.addPathConstraint(sh, "/open");
-
- // Server wide (breaks "open" tests)
- if ( ConstraintServer )
- JettyLib.addPathConstraint(sh, "/*");
-
- DataService dSrv = new DataService(DatasetGraphFactory.createTxnMem());
- FusekiBuilder.populateStdServices(dSrv, false);
- dSrv.setAllowedUsers(Arrays.asList("user1"));
-
- fusekiServer =
- FusekiServer.create()
- .port(port)
- .add("/ds", DatasetFactory.createTxnMem())
- .add("/open", DatasetFactory.createTxnMem())
- .add("/ctl", dSrv)
- .securityHandler(sh)
- //.staticFileBase(".")
- .build();
- fusekiServer.start();
- }
-
- @Before
- public void before() {
- // Reset before every test and after the suite.
- HttpClient hc = HttpOp.createDefaultHttpClient();
- HttpOp.setDefaultHttpClient(hc);
- }
-
-
- @AfterClass
- public static void afterClass() {
- fusekiServer.stop();
- HttpClient hc = HttpOp.createDefaultHttpClient();
- HttpOp.setDefaultHttpClient(hc);
- }
-
- // Server authentication.
-
- @Test public void access_server() {
- assumeFalse(ConstraintServer);
- try( TypedInputStream in = HttpOp.execHttpGet(serverURL) ) {
- assertNotNull(in);
- fail("Didn't expect to succeed");
- } catch (HttpException ex) {
- // 404 is OK - no static file area.
- if ( ex.getResponseCode() != HttpSC.NOT_FOUND_404 )
- throw ex;
- }
- }
-
- @Test public void access_open() {
- assumeFalse(ConstraintServer);
- try( TypedInputStream in = HttpOp.execHttpGet(serverURL+"open") ) {
- assertNotNull(in);
- }
- }
-
- @Test public void access_open_user1() {
- // OK.
- LibSec.withAuth(serverURL+"open", authSetup1, (conn)->{
- conn.queryAsk("ASK{}");
- });
- }
-
- @Test public void access_open_userX() {
- assumeFalse(ConstraintServer);
- // OK.
- LibSec.withAuth(serverURL+"open", authSetupX, (conn)->{
- conn.queryAsk("ASK{}");
- });
- }
-
-
- // Should fail.
- @Test public void access_deny_ds() {
- try( TypedInputStream in = HttpOp.execHttpGet(serverURL+"ds") ) {
- fail("Didn't expect to succeed");
- } catch (HttpException ex) {
- if ( ex.getResponseCode() != HttpSC.UNAUTHORIZED_401 )
- throw ex;
- }
- }
-
- // Should be 401, not be 404.
- @Test public void access_deny_nowhere() {
- try( TypedInputStream in = HttpOp.execHttpGet(serverURL+"nowhere") ) {
- fail("Didn't expect to succeed");
- } catch (HttpException ex) {
- if ( ex.getResponseCode() != HttpSC.UNAUTHORIZED_401 )
- throw ex;
- }
- }
-
- @Test public void access_allow_nowhere() {
- HttpClient hc = LibSec.httpClient(authSetup1);
- HttpCaptureResponse<TypedInputStream> handler = new CaptureInput();
- try( TypedInputStream in = HttpOp.execHttpGet(serverURL+"nowhere", null, hc, null) ) {
- // null for 404.
- assertNull(in);
- } catch (HttpException ex) {
- if ( ex.getResponseCode() != HttpSC.NOT_FOUND_404)
- throw ex;
- }
- }
-
- @Test public void access_allow_ds() {
- HttpClient hc = LibSec.httpClient(authSetup1);
- HttpCaptureResponse<TypedInputStream> handler = new CaptureInput();
- try( TypedInputStream in = HttpOp.execHttpGet(serverURL+"ds", null, hc, null) ) {
- assertNotNull(in);
- }
- }
-
- // Service level : ctl.
-
- @Test public void access_service_ctl_user1() {
- // user1 -- allowed.
- HttpClient hc = LibSec.httpClient(authSetup1);
- try( TypedInputStream in = HttpOp.execHttpGet(serverURL+"ctl", null, hc, null) ) {
- assertNotNull(in);
- }
- }
-
- @Test public void access_service_ctl_user2() {
- // user2 -- can login, not allowed.
- HttpClient hc = LibSec.httpClient(authSetup2);
- try( TypedInputStream in = HttpOp.execHttpGet(serverURL+"ctl", null, hc, null) ) {
- fail("Didn't expect to succeed");
- } catch (HttpException ex) {
- if ( ex.getResponseCode() != HttpSC.FORBIDDEN_403)
- throw ex;
- }
- }
-
- @Test public void access_service_ctl_userX() {
- // userX -- can't login, not allowed.
- HttpClient hc = LibSec.httpClient(authSetupX);
- try( TypedInputStream in = HttpOp.execHttpGet(serverURL+"ctl", null, hc, null) ) {
- fail("Didn't expect to succeed");
- } catch (HttpException ex) {
- if ( ex.getResponseCode() != HttpSC.UNAUTHORIZED_401)
- throw ex;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/jena/blob/fcbcc78e/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestPasswordServer.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestPasswordServer.java b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestPasswordServer.java
new file mode 100644
index 0000000..b160db2
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestPasswordServer.java
@@ -0,0 +1,217 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.fuseki.access;
+
+import static org.junit.Assert.assertNull;
+
+import org.apache.http.client.HttpClient;
+import org.apache.jena.atlas.web.HttpException;
+import org.apache.jena.atlas.web.TypedInputStream;
+import org.apache.jena.atlas.web.WebLib;
+import org.apache.jena.fuseki.jetty.JettyLib;
+import org.apache.jena.fuseki.main.FusekiServer;
+import org.apache.jena.rdfconnection.RDFConnection;
+import org.apache.jena.rdfconnection.RDFConnectionRemote;
+import org.apache.jena.riot.web.HttpOp;
+import org.apache.jena.sparql.engine.http.QueryExceptionHTTP;
+import org.apache.jena.web.HttpSC;
+import org.eclipse.jetty.security.ConstraintSecurityHandler;
+import org.eclipse.jetty.security.UserStore;
+import org.junit.After;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/** Tests for
+ * <ul>
+ * <li>password access at the server-level
+ * <li>assembler file
+ * </ul>
+ */
+public class TestPasswordServer {
+
+ // Per test.
+ private FusekiServer fusekiServer = null;
+
+ private static String REALM = "TripleStore";
+ private AuthSetup authSetup1(FusekiServer server) { return new AuthSetup("localhost", server.getPort(), "user1", "pw1", REALM); }
+ private AuthSetup authSetup2(FusekiServer server) { return new AuthSetup("localhost", server.getPort(), "user2", "pw2", REALM); }
+ private AuthSetup authSetup3(FusekiServer server) { return new AuthSetup("localhost", server.getPort(), "user3", "pw3", REALM); }
+ // Not in the user store.
+ private AuthSetup authSetupX(FusekiServer server) { return new AuthSetup("localhost", server.getPort(), "userX", "pwX", REALM); }
+
+ private static String serverURL(FusekiServer server) {
+ return "http://localhost:"+server.getPort()+"/";
+ }
+
+ private FusekiServer fusekiServer(String configFile) {
+ int port = WebLib.choosePort();
+ // Read from assembler+passwd file.
+ UserStore userStore = JettyLib.makeUserStore("testing/Access/passwd");
+ ConstraintSecurityHandler sh = JettyLib.makeSecurityHandler(REALM, userStore);
+
+ fusekiServer =
+ FusekiServer.create()
+ .port(port)
+ .parseConfigFile(configFile)
+ .securityHandler(sh)
+ //.staticFileBase(".")
+ .build();
+ fusekiServer.start();
+ return fusekiServer;
+ }
+
+ @BeforeClass
+ public static void beforeClass() {
+ // Reset before every test and after the suite.
+ HttpClient hc = HttpOp.createDefaultHttpClient();
+ HttpOp.setDefaultHttpClient(hc);
+ }
+
+ @After
+ public void after() {
+ if ( fusekiServer != null )
+ fusekiServer.stop();
+ HttpClient hc = HttpOp.createDefaultHttpClient();
+ HttpOp.setDefaultHttpClient(hc);
+ }
+
+ private static void expectQuery403(Runnable action) {
+ try{
+ action.run();
+ throw new HttpException("action completed");
+ } catch (QueryExceptionHTTP ex) {
+ // 404 is OK - no static file area.
+ if ( ex.getResponseCode() != HttpSC.FORBIDDEN_403 )
+ throw ex;
+ }
+ }
+
+ // Server authentication.
+
+ @Test public void access_serverAny_user1() {
+ FusekiServer fusekiServer = fusekiServer("testing/Access/config-server-1.ttl");
+ try {
+ // Must be logged in.
+ HttpClient hc = LibSec.httpClient(authSetup1(fusekiServer));
+ try( TypedInputStream in = HttpOp.execHttpGet(serverURL(fusekiServer), null, hc, null) ) {
+ assertNull(in);
+ } catch (HttpException ex) {
+ // 404 is OK - no static file area.
+ if ( ex.getResponseCode() != HttpSC.NOT_FOUND_404 )
+ throw ex;
+ }
+ } finally {
+ fusekiServer.stop();
+ fusekiServer = null;
+ }
+ }
+
+ @Test public void access_serverAny_db1() {
+ FusekiServer fusekiServer = fusekiServer("testing/Access/config-server-1.ttl");
+ try {
+ // Must be logged in.
+ HttpClient hc = LibSec.httpClient(authSetup1(fusekiServer));
+ try ( RDFConnection conn = RDFConnectionRemote
+ .create().destination(serverURL(fusekiServer)+"/database1").httpClient(hc).build() ) {
+ conn.queryAsk("ASK{}");
+ }
+ } finally {
+ fusekiServer.stop();
+ fusekiServer = null;
+ }
+ }
+
+ @Test public void access_serverAny_db2() {
+ FusekiServer fusekiServer = fusekiServer("testing/Access/config-server-1.ttl");
+ try {
+ // Must be logged in.
+ HttpClient hc = LibSec.httpClient(authSetup1(fusekiServer));
+ try ( RDFConnection conn = RDFConnectionRemote
+ .create().destination(serverURL(fusekiServer)+"/database2").httpClient(hc).build() ) {
+ conn.queryAsk("ASK{}");
+ }
+ } finally {
+ fusekiServer.stop();
+ fusekiServer = null;
+ }
+ }
+
+ @Test public void access_serverAny_db1_wrongUser() {
+ FusekiServer fusekiServer = fusekiServer("testing/Access/config-server-1.ttl");
+ try {
+ // Must be logged in.
+ HttpClient hc = LibSec.httpClient(authSetup2(fusekiServer)); // 2
+ try ( RDFConnection conn = RDFConnectionRemote
+ .create().destination(serverURL(fusekiServer)+"/database1").httpClient(hc).build() ) {
+ expectQuery403(()->conn.queryAsk("ASK{}"));
+ }
+ } finally {
+ fusekiServer.stop();
+ fusekiServer = null;
+ }
+ }
+
+ // Specific server user.
+ @Test public void access_serverUser_user1() {
+ FusekiServer fusekiServer = fusekiServer("testing/Access/config-server-2.ttl");
+ try {
+ // Must be logged in as user1
+ HttpClient hc = LibSec.httpClient(authSetup1(fusekiServer));
+ try ( RDFConnection conn = RDFConnectionRemote
+ .create().destination(serverURL(fusekiServer)+"/database1").httpClient(hc).build() ) {
+ conn.queryAsk("ASK{}");
+ }
+ } finally {
+ fusekiServer.stop();
+ fusekiServer = null;
+ }
+ }
+
+ // Specific server user.
+ @Test public void access_serverUser_user2() {
+ FusekiServer fusekiServer = fusekiServer("testing/Access/config-server-2.ttl");
+ try {
+ // user2 does not have service access
+ HttpClient hc = LibSec.httpClient(authSetup2(fusekiServer));
+ try ( RDFConnection conn = RDFConnectionRemote
+ .create().destination(serverURL(fusekiServer)+"/database1").httpClient(hc).build() ) {
+ expectQuery403(()->conn.queryAsk("ASK{}"));
+ }
+ } finally {
+ fusekiServer.stop();
+ fusekiServer = null;
+ }
+ }
+
+ // Specific server user.
+ @Test public void access_serverUser_user3() {
+ FusekiServer fusekiServer = fusekiServer("testing/Access/config-server-2.ttl");
+ try {
+ // user3 does not have server access
+ HttpClient hc = LibSec.httpClient(authSetup3(fusekiServer));
+ try ( RDFConnection conn = RDFConnectionRemote
+ .create().destination(serverURL(fusekiServer)+"/database1").httpClient(hc).build() ) {
+ expectQuery403(()->conn.queryAsk("ASK{}"));
+ }
+ } finally {
+ fusekiServer.stop();
+ fusekiServer = null;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/fcbcc78e/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestPasswordServices.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestPasswordServices.java b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestPasswordServices.java
new file mode 100644
index 0000000..0183728
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestPasswordServices.java
@@ -0,0 +1,230 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.fuseki.access;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+import org.apache.http.client.HttpClient;
+import org.apache.jena.atlas.logging.LogCtl;
+import org.apache.jena.atlas.web.HttpException;
+import org.apache.jena.atlas.web.TypedInputStream;
+import org.apache.jena.atlas.web.WebLib;
+import org.apache.jena.fuseki.build.FusekiBuilder;
+import org.apache.jena.fuseki.build.RequestAuthorization;
+import org.apache.jena.fuseki.jetty.JettyLib;
+import org.apache.jena.fuseki.main.FusekiServer;
+import org.apache.jena.fuseki.server.DataService;
+import org.apache.jena.query.DatasetFactory;
+import org.apache.jena.riot.web.HttpCaptureResponse;
+import org.apache.jena.riot.web.HttpOp;
+import org.apache.jena.riot.web.HttpOp.CaptureInput;
+import org.apache.jena.sparql.core.DatasetGraphFactory;
+import org.apache.jena.web.HttpSC;
+import org.eclipse.jetty.security.ConstraintSecurityHandler;
+import org.eclipse.jetty.security.UserStore;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * Tests for password access to services when there is no server-level access control
+ * and also programmatic setup.
+ * <p>
+ * See {@link TestPasswordServer} for tests with server-level access control
+ * and also access control by assembler
+ * <p>
+ * See {@link TestSecurityFilterFuseki} for graph-level access control.
+ *
+ */
+public class TestPasswordServices {
+
+ private static FusekiServer fusekiServer = null;
+ private static int port = WebLib.choosePort();
+ private static String serverURL = "http://localhost:"+port+"/";
+ private static AuthSetup authSetup1 = new AuthSetup("localhost", port, "user1", "pw1", "TripleStore");
+ private static AuthSetup authSetup2 = new AuthSetup("localhost", port, "user2", "pw2", "TripleStore");
+ // Not in the user store.
+ private static AuthSetup authSetupX = new AuthSetup("localhost", port, "userX", "pwX", "TripleStore");
+
+ @BeforeClass
+ public static void beforeClass() {
+ if ( false )
+ // To watch the HTTP headers
+ LogCtl.enable("org.apache.http.headers");
+
+ // Two authorized users.
+ UserStore userStore = new UserStore();
+ JettyLib.addUser(userStore, authSetup1.user, authSetup1.password);
+ JettyLib.addUser(userStore, authSetup2.user, authSetup2.password);
+ try { userStore.start(); }
+ catch (Exception ex) { throw new RuntimeException("UserStore", ex); }
+
+ ConstraintSecurityHandler sh = JettyLib.makeSecurityHandler(authSetup1.realm, userStore);
+
+ // Secure these areas.
+ // User needs to be logged in.
+ JettyLib.addPathConstraint(sh, "/ds");
+ // Allow auth control even through there isn't anything there
+ JettyLib.addPathConstraint(sh, "/nowhere");
+ // user1 only.
+ JettyLib.addPathConstraint(sh, "/ctl");
+
+ // Not controlled: "/open"
+
+ DataService dSrv = new DataService(DatasetGraphFactory.createTxnMem());
+ FusekiBuilder.populateStdServices(dSrv, false);
+ RequestAuthorization reqAuth = RequestAuthorization.policyAllowSpecific("user1");
+ dSrv.setAllowedUsers(reqAuth);
+
+ fusekiServer =
+ FusekiServer.create()
+ .port(port)
+ .add("/ds", DatasetFactory.createTxnMem())
+ .add("/open", DatasetFactory.createTxnMem())
+ .add("/ctl", dSrv)
+ .securityHandler(sh)
+ //.staticFileBase(".")
+ .build();
+ fusekiServer.start();
+ }
+
+ @Before
+ public void before() {
+ // Reset before every test and after the suite.
+ HttpClient hc = HttpOp.createDefaultHttpClient();
+ HttpOp.setDefaultHttpClient(hc);
+ }
+
+
+ @AfterClass
+ public static void afterClass() {
+ fusekiServer.stop();
+ HttpClient hc = HttpOp.createDefaultHttpClient();
+ HttpOp.setDefaultHttpClient(hc);
+ }
+
+ // Server authentication.
+
+ @Test public void access_server() {
+ try( TypedInputStream in = HttpOp.execHttpGet(serverURL) ) {
+ assertNotNull(in);
+ fail("Didn't expect to succeed");
+ } catch (HttpException ex) {
+ // 404 is OK - no static file area.
+ if ( ex.getResponseCode() != HttpSC.NOT_FOUND_404 )
+ throw ex;
+ }
+ }
+
+ @Test public void access_open() {
+ try( TypedInputStream in = HttpOp.execHttpGet(serverURL+"open") ) {
+ assertNotNull(in);
+ }
+ }
+
+ @Test public void access_open_user1() {
+ // OK.
+ LibSec.withAuth(serverURL+"open", authSetup1, (conn)->{
+ conn.queryAsk("ASK{}");
+ });
+ }
+
+ @Test public void access_open_userX() {
+ // OK.
+ LibSec.withAuth(serverURL+"open", authSetupX, (conn)->{
+ conn.queryAsk("ASK{}");
+ });
+ }
+
+
+ // Should fail.
+ @Test public void access_deny_ds() {
+ try( TypedInputStream in = HttpOp.execHttpGet(serverURL+"ds") ) {
+ fail("Didn't expect to succeed");
+ } catch (HttpException ex) {
+ if ( ex.getResponseCode() != HttpSC.UNAUTHORIZED_401 )
+ throw ex;
+ }
+ }
+
+ // Should be 401, not be 404.
+ @Test public void access_deny_nowhere() {
+ try( TypedInputStream in = HttpOp.execHttpGet(serverURL+"nowhere") ) {
+ fail("Didn't expect to succeed");
+ } catch (HttpException ex) {
+ if ( ex.getResponseCode() != HttpSC.UNAUTHORIZED_401 )
+ throw ex;
+ }
+ }
+
+ @Test public void access_allow_nowhere() {
+ HttpClient hc = LibSec.httpClient(authSetup1);
+ HttpCaptureResponse<TypedInputStream> handler = new CaptureInput();
+ try( TypedInputStream in = HttpOp.execHttpGet(serverURL+"nowhere", null, hc, null) ) {
+ // null for 404.
+ assertNull(in);
+ } catch (HttpException ex) {
+ if ( ex.getResponseCode() != HttpSC.NOT_FOUND_404)
+ throw ex;
+ }
+ }
+
+ @Test public void access_allow_ds() {
+ HttpClient hc = LibSec.httpClient(authSetup1);
+ HttpCaptureResponse<TypedInputStream> handler = new CaptureInput();
+ try( TypedInputStream in = HttpOp.execHttpGet(serverURL+"ds", null, hc, null) ) {
+ assertNotNull(in);
+ }
+ }
+
+ // Service level : ctl.
+
+ @Test public void access_service_ctl_user1() {
+ // user1 -- allowed.
+ HttpClient hc = LibSec.httpClient(authSetup1);
+ try( TypedInputStream in = HttpOp.execHttpGet(serverURL+"ctl", null, hc, null) ) {
+ assertNotNull(in);
+ }
+ }
+
+ @Test public void access_service_ctl_user2() {
+ // user2 -- can login, not allowed.
+ HttpClient hc = LibSec.httpClient(authSetup2);
+ try( TypedInputStream in = HttpOp.execHttpGet(serverURL+"ctl", null, hc, null) ) {
+ fail("Didn't expect to succeed");
+ } catch (HttpException ex) {
+ if ( ex.getResponseCode() != HttpSC.FORBIDDEN_403)
+ throw ex;
+ }
+ }
+
+ @Test public void access_service_ctl_userX() {
+ // userX -- can't login, not allowed.
+ HttpClient hc = LibSec.httpClient(authSetupX);
+ try( TypedInputStream in = HttpOp.execHttpGet(serverURL+"ctl", null, hc, null) ) {
+ fail("Didn't expect to succeed");
+ } catch (HttpException ex) {
+ if ( ex.getResponseCode() != HttpSC.UNAUTHORIZED_401)
+ throw ex;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jena/blob/fcbcc78e/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityAssemblerBuild.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityAssemblerBuild.java b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityAssemblerBuild.java
index 54cab0d..ade838b 100644
--- a/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityAssemblerBuild.java
+++ b/jena-fuseki2/jena-fuseki-access/src/test/java/org/apache/jena/fuseki/access/TestSecurityAssemblerBuild.java
@@ -25,6 +25,7 @@ import org.apache.jena.sparql.core.assembler.AssemblerUtils;
import org.apache.jena.sys.JenaSystem;
import org.junit.Test;
+/** Test parsing of assembers with security aspects */
public class TestSecurityAssemblerBuild {
static { JenaSystem.init(); }
static final String DIR = "testing/Access/";
http://git-wip-us.apache.org/repos/asf/jena/blob/fcbcc78e/jena-fuseki2/jena-fuseki-access/testing/Access/allowedUsers.ttl
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/testing/Access/allowedUsers.ttl b/jena-fuseki2/jena-fuseki-access/testing/Access/allowedUsers.ttl
new file mode 100644
index 0000000..d674a64
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/testing/Access/allowedUsers.ttl
@@ -0,0 +1,15 @@
+PREFIX : <http://example/>
+PREFIX fuseki: <http://jena.apache.org/fuseki#>
+PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
+PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
+PREFIX tdb2: <http://jena.apache.org/2016/tdb#>
+PREFIX ja: <http://jena.hpl.hp.com/2005/11/Assembler#>
+PREFIX access: <http://jena.apache.org/access#>
+
+:none :p 123 .
+
+:r1 fuseki:allowedUsers "user1" ,"user2" .
+:r2 fuseki:allowedUsers ( "user1" "user2" ) .
+
+:rLoggedIn fuseki:allowedUsers "*" .
+
http://git-wip-us.apache.org/repos/asf/jena/blob/fcbcc78e/jena-fuseki2/jena-fuseki-access/testing/Access/assem-security.ttl
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/testing/Access/assem-security.ttl b/jena-fuseki2/jena-fuseki-access/testing/Access/assem-security.ttl
index 8d04b8e..8506be3 100644
--- a/jena-fuseki2/jena-fuseki-access/testing/Access/assem-security.ttl
+++ b/jena-fuseki2/jena-fuseki-access/testing/Access/assem-security.ttl
@@ -52,7 +52,7 @@ PREFIX access: <http://jena.apache.org/access#>
fuseki:serviceQuery "sparql";
fuseki:serviceUpdate "update";
fuseki:serviceUpload "upload" ;
- fuseki:serviceReadGraphStore "data" ;
+ fuseki:serviceReadWriteGraphStore "data" ;
fuseki:serviceReadGraphStore "get" ;
fuseki:dataset <#tdb_dataset> ;
.
http://git-wip-us.apache.org/repos/asf/jena/blob/fcbcc78e/jena-fuseki2/jena-fuseki-access/testing/Access/config-server-1.ttl
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/testing/Access/config-server-1.ttl b/jena-fuseki2/jena-fuseki-access/testing/Access/config-server-1.ttl
new file mode 100644
index 0000000..ce42505
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/testing/Access/config-server-1.ttl
@@ -0,0 +1,43 @@
+PREFIX : <#>
+PREFIX fuseki: <http://jena.apache.org/fuseki#>
+PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
+PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
+PREFIX tdb2: <http://jena.apache.org/2016/tdb#>
+PREFIX ja: <http://jena.hpl.hp.com/2005/11/Assembler#>
+PREFIX access: <http://jena.apache.org/access#>
+
+[] rdf:type fuseki:Server ;
+ fuseki:allowedUsers "*";
+ fuseki:services (
+ <#service_tdb2>
+ <#service_plain>
+ ) .
+
+<#service_tdb2> rdf:type fuseki:Service ;
+ rdfs:label "Access controlled dataset" ;
+ fuseki:allowedUsers "user1", "user3";
+ fuseki:name "database1" ;
+ fuseki:serviceQuery "query" ;
+ fuseki:serviceQuery "sparql" ;
+ fuseki:serviceReadGraphStore "get" ;
+ fuseki:dataset <#dataset1>;
+ .
+
+## Own database
+<#dataset1> rdf:type ja:MemoryDataset ;
+ .
+
+## Dataset 2
+## No service
+<#service_plain> rdf:type fuseki:Service ;
+ fuseki:name "database2";
+ fuseki:serviceQuery "query";
+ fuseki:serviceQuery "sparql";
+ fuseki:serviceReadGraphStore "get" ;
+ fuseki:dataset <#tdb_dataset> ;
+ .
+
+<#tdb_dataset> rdf:type tdb2:DatasetTDB2 ;
+ tdb2:location "--mem--" ;
+ .
+
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jena/blob/fcbcc78e/jena-fuseki2/jena-fuseki-access/testing/Access/config-server-2.ttl
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/testing/Access/config-server-2.ttl b/jena-fuseki2/jena-fuseki-access/testing/Access/config-server-2.ttl
new file mode 100644
index 0000000..cf9a1fc
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/testing/Access/config-server-2.ttl
@@ -0,0 +1,43 @@
+PREFIX : <#>
+PREFIX fuseki: <http://jena.apache.org/fuseki#>
+PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
+PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
+PREFIX tdb2: <http://jena.apache.org/2016/tdb#>
+PREFIX ja: <http://jena.hpl.hp.com/2005/11/Assembler#>
+PREFIX access: <http://jena.apache.org/access#>
+
+[] rdf:type fuseki:Server ;
+ fuseki:allowedUsers "user1", "user2";
+ fuseki:services (
+ <#service_tdb2>
+ <#service_plain>
+ ) .
+
+<#service_tdb2> rdf:type fuseki:Service ;
+ rdfs:label "Access controlled dataset" ;
+ fuseki:allowedUsers "user1", "user3";
+ fuseki:name "database1" ;
+ fuseki:serviceQuery "query" ;
+ fuseki:serviceQuery "sparql" ;
+ fuseki:serviceReadGraphStore "get" ;
+ fuseki:dataset <#dataset1>;
+ .
+
+## Own database
+<#dataset1> rdf:type ja:MemoryDataset ;
+ .
+
+## Dataset 2
+## No service
+<#service_plain> rdf:type fuseki:Service ;
+ fuseki:name "database2";
+ fuseki:serviceQuery "query";
+ fuseki:serviceQuery "sparql";
+ fuseki:serviceReadGraphStore "get" ;
+ fuseki:dataset <#tdb_dataset> ;
+ .
+
+<#tdb_dataset> rdf:type tdb2:DatasetTDB2 ;
+ tdb2:location "--mem--" ;
+ .
+
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jena/blob/fcbcc78e/jena-fuseki2/jena-fuseki-access/testing/Access/passwd
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-access/testing/Access/passwd b/jena-fuseki2/jena-fuseki-access/testing/Access/passwd
new file mode 100644
index 0000000..c856f0a
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-access/testing/Access/passwd
@@ -0,0 +1,3 @@
+user1 :pw1
+user2: pw2
+user3: pw3
http://git-wip-us.apache.org/repos/asf/jena/blob/fcbcc78e/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiBuildLib.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiBuildLib.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiBuildLib.java
index e23d74e..5bad1ce 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiBuildLib.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiBuildLib.java
@@ -33,7 +33,9 @@ import org.apache.jena.shared.JenaException;
import org.apache.jena.shared.PrefixMapping ;
import org.apache.jena.vocabulary.RDFS ;
-/** Library code for operations specific to building Fuseki servers and services. */
+/**
+ * Library code for operations related to building Fuseki servers and services.
+ */
public class FusekiBuildLib {
// ---- Helper code
http://git-wip-us.apache.org/repos/asf/jena/blob/fcbcc78e/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiBuilder.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiBuilder.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiBuilder.java
index c9fe706..a6fdd8a 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiBuilder.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiBuilder.java
@@ -18,15 +18,25 @@
package org.apache.jena.fuseki.build;
+import static java.lang.String.format;
+import static java.util.stream.Collectors.toList;
+import static org.apache.jena.fuseki.server.FusekiVocab.pAllowedUsers;
+
+import java.util.Collection;
+import java.util.List;
+
import org.apache.jena.fuseki.FusekiConfigException;
import org.apache.jena.fuseki.server.DataAccessPoint;
import org.apache.jena.fuseki.server.DataAccessPointRegistry;
import org.apache.jena.fuseki.server.DataService ;
import org.apache.jena.fuseki.server.Operation ;
+import org.apache.jena.graph.Node;
import org.apache.jena.query.QuerySolution ;
import org.apache.jena.query.ResultSet ;
import org.apache.jena.rdf.model.Property ;
+import org.apache.jena.rdf.model.RDFNode;
import org.apache.jena.rdf.model.Resource ;
+import org.apache.jena.rdf.model.impl.Util;
import org.apache.jena.sparql.core.DatasetGraph ;
/**
@@ -101,5 +111,36 @@ public class FusekiBuilder
name = DataAccessPoint.canonical(name);
dataAccessPoints.remove(name);
}
+
+ /** Get the allowed users on some resources.
+ * Returns null if the resource is null or if there were no settings.
+ *
+ * @param resource
+ * @return RequestAuthorization
+ */
+ public static RequestAuthorization allowedUsers(Resource resource) {
+ if ( resource == null )
+ return null;
+ Collection<RDFNode> allowedUsers = FusekiBuildLib.getAll(resource, "fu:"+pAllowedUsers.getLocalName());
+ if ( allowedUsers == null )
+ // Indicate no settings.
+ return null;
+ // Check all values are simple strings
+ List<String> bad = allowedUsers.stream()
+ .map(RDFNode::asNode)
+ .filter(rn -> ! Util.isSimpleString(rn))
+ .map(rn->rn.toString())
+ .collect(toList());
+ if ( ! bad.isEmpty() ) {
+ //Fuseki.configLog.error(format("User names must be a simple string: bad = %s", bad));
+ throw new FusekiConfigException(format("User names should be a simple string: bad = %s", bad));
+ }
+ // RDFNodes/literals to strings.
+ Collection<String> userNames = allowedUsers.stream()
+ .map(RDFNode::asNode)
+ .map(Node::getLiteralLexicalForm)
+ .collect(toList());
+ return RequestAuthorization.policyAllowSpecific(userNames);
+ }
}
http://git-wip-us.apache.org/repos/asf/jena/blob/fcbcc78e/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiConfig.java
----------------------------------------------------------------------
diff --git a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiConfig.java b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiConfig.java
index f6ab055..5dc34e3 100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiConfig.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/build/FusekiConfig.java
@@ -19,7 +19,6 @@
package org.apache.jena.fuseki.build ;
import static java.lang.String.format;
-import static java.util.stream.Collectors.toList;
import static org.apache.jena.fuseki.server.FusekiVocab.*;
import static org.apache.jena.riot.RDFLanguages.filenameToLang;
import static org.apache.jena.riot.RDFParserRegistry.isRegistered;
@@ -31,10 +30,7 @@ import java.nio.file.DirectoryStream ;
import java.nio.file.Files ;
import java.nio.file.Path ;
import java.nio.file.Paths ;
-import java.util.ArrayList ;
-import java.util.Collection;
-import java.util.Collections ;
-import java.util.List ;
+import java.util.*;
import org.apache.jena.assembler.Assembler;
import org.apache.jena.assembler.JA ;
@@ -44,13 +40,11 @@ import org.apache.jena.datatypes.xsd.XSDDatatype;
import org.apache.jena.fuseki.Fuseki ;
import org.apache.jena.fuseki.FusekiConfigException ;
import org.apache.jena.fuseki.server.*;
-import org.apache.jena.graph.Node;
import org.apache.jena.query.Dataset ;
import org.apache.jena.query.QuerySolution ;
import org.apache.jena.query.ReadWrite ;
import org.apache.jena.query.ResultSet ;
import org.apache.jena.rdf.model.*;
-import org.apache.jena.rdf.model.impl.Util;
import org.apache.jena.riot.Lang;
import org.apache.jena.sparql.core.assembler.AssemblerUtils ;
import org.apache.jena.sparql.util.Context;
@@ -85,6 +79,29 @@ public class FusekiConfig {
return x;
}
+ /**
+ * Process a configuration file, starting {@code server}.
+ * Return the {@link DataAccessPoint DataAccessPoints}
+ * set the context provided for server-wide settings.
+ *
+ * This bundles together the steps:
+ * <ul>
+ * <li>{@link #findServer}
+ * <li>{@link #processContext}
+ * <li>{@link #processLoadClass} (legacy)
+ * <li>{@link #servicesAndDatasets}
+ * </ul>
+ */
+ public static List<DataAccessPoint> processServerConfiguration(Resource server, Context context) {
+ Objects.requireNonNull(server);
+ FusekiConfig.processContext(server, context);
+ FusekiConfig.processLoadClass(server);
+ // Process services, whether via server ja:services or, if absent, by finding by type.
+ List<DataAccessPoint> x = FusekiConfig.servicesAndDatasets(server);
+ return x;
+ }
+
+
/* Find the server resource in a configuration file.
* Returns null if there isn't one.
* Raises {@link FusekiConfigException} is there are more than one.
@@ -144,24 +161,36 @@ public class FusekiConfig {
/** Find and process datasets and services in a configuration file.
* This can be a Fuseki server configuration file or a services-only configuration file.
* It looks {@code fuseki:services ( .... )} then, if not found, all {@code rtdf:type fuseki:services}.
- * This is the main entry point to processing Fuseki configuration files.
+ * @see #processServerConfiguration
*/
public static List<DataAccessPoint> servicesAndDatasets(Model model) {
Resource server = findServer(model);
- if ( server != null )
- AssemblerUtils.setContext(server, Fuseki.getContext()) ;
-
- // Old style configuration file : server to services.
+ return servicesAndDatasets$(server, model);
+ }
+
+ /** Find and process datasets and services in a configuration file
+ * starting from {@code server} which can have a {@code fuseki:services ( .... )}
+ * but, if not found, all {@code rtdf:type fuseki:services} are processed.
+ */
+ public static List<DataAccessPoint> servicesAndDatasets(Resource server) {
+ Objects.requireNonNull(server);
+ return servicesAndDatasets$(server, server.getModel());
+ }
+
+ private static List<DataAccessPoint> servicesAndDatasets$(Resource server, Model model) {
DatasetDescriptionRegistry dsDescMap = new DatasetDescriptionRegistry();
// ---- Services
+ // Server to services.
ResultSet rs = FusekiBuildLib.query("SELECT * { ?s fu:services [ list:member ?service ] }", model, "s", server) ;
List<DataAccessPoint> accessPoints = new ArrayList<>() ;
+ // If none, look for services by type.
if ( ! rs.hasNext() )
// No "fu:services ( .... )" so try looking for services directly.
// This means Fuseki2, service configuration files (no server section) work for --conf.
rs = FusekiBuildLib.query("SELECT ?service { ?service a fu:Service }", model) ;
+ // rs is a result set of services to process.
for ( ; rs.hasNext() ; ) {
QuerySolution soln = rs.next() ;
Resource svc = soln.getResource("service") ;
@@ -257,40 +286,12 @@ public class FusekiConfig {
String name = object.getLexicalForm() ;
name = DataAccessPoint.canonical(name) ;
DataService dataService = buildDataService(svc, dsDescMap) ;
- Collection<String> allowedUsers = getAllowedUsers(svc);
+ RequestAuthorization allowedUsers = FusekiBuilder.allowedUsers(svc);
dataService.setAllowedUsers(allowedUsers);
DataAccessPoint dataAccess = new DataAccessPoint(name, dataService) ;
return dataAccess ;
}
- /** Get the allowed users on some resources.
- *
- * @param resource
- * @return Collection<String>
- */
- public static Collection<String> getAllowedUsers(Resource resource) {
- Collection<RDFNode> allowedUsers = FusekiBuildLib.getAll(resource, "fu:"+pAllowedUsers.getLocalName());
- Collection<String> userNames = null;
- if ( allowedUsers != null ) {
- // Check all values are simple strings
- List<String> bad = allowedUsers.stream()
- .map(RDFNode::asNode)
- .filter(rn -> ! Util.isSimpleString(rn))
- .map(rn->rn.toString())
- .collect(toList());
- if ( ! bad.isEmpty() ) {
- //Fuseki.configLog.error(format("User names must be a simple string: bad = %s", bad));
- throw new FusekiConfigException(format("User names should be a simple string: bad = %s", bad));
- }
- // RDFNodes/literals to strings.
- userNames = allowedUsers.stream()
- .map(RDFNode::asNode)
- .map(Node::getLiteralLexicalForm)
- .collect(toList());
- }
- return userNames;
- }
-
/** Build a DatasetRef starting at Resource svc, having the services as described by the descriptions. */
private static DataService buildDataService(Resource svc, DatasetDescriptionRegistry dsDescMap) {
Resource datasetDesc = ((Resource)FusekiBuildLib.getOne(svc, "fu:dataset")) ;