This is an automated email from the ASF dual-hosted git repository.
kinow pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/jena.git
The following commit(s) were added to refs/heads/main by this push:
new 677a22decf GH-2370: Improve validation of dataset graph names
677a22decf is described below
commit 677a22decfdffbcdbd187dd3223d95343b5dc381
Author: Bruno P. Kinoshita <[email protected]>
AuthorDate: Wed Mar 27 13:00:24 2024 +0100
GH-2370: Improve validation of dataset graph names
---
.../jena-fuseki-ui/src/utils/validation.js | 48 +++++++++++++
.../jena-fuseki-ui/src/views/dataset/Upload.vue | 15 ++--
.../tests/unit/utils/validation.spec.js | 84 ++++++++++++++++++++++
3 files changed, 138 insertions(+), 9 deletions(-)
diff --git a/jena-fuseki2/jena-fuseki-ui/src/utils/validation.js
b/jena-fuseki2/jena-fuseki-ui/src/utils/validation.js
new file mode 100644
index 0000000000..fd45116f91
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-ui/src/utils/validation.js
@@ -0,0 +1,48 @@
+/**
+ * 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.
+ */
+
+/*
+ * Utility functions for data validation in the UI.
+ *
+ * We must avoid repeating the validation when the backend server is handling
this,
+ * unless we really want to do that (avoid large payloads, for security, etc.).
+ */
+
+/**
+ * Validates a Jena UI graph name.
+ *
+ * @param {string} graphName - The name of the graph provided by user or
configuration file.
+ * @return {boolean} - true iff the given name of the graph provided is valid
for Jena.
+ */
+export function validateGraphName (graphName) {
+ if (graphName === '' || graphName.trim() === '') {
+ return false
+ }
+ // No spaces allowed in graph names.
+ const pattern = /^\S+$/
+ if (!pattern.test(graphName)) {
+ return false
+ }
+ // Only valid URIs allowed.
+ try {
+ new URL(graphName)
+ } catch {
+ return false
+ }
+ // If it reached this part, then it's a valid graph name.
+ return true
+}
diff --git a/jena-fuseki2/jena-fuseki-ui/src/views/dataset/Upload.vue
b/jena-fuseki2/jena-fuseki-ui/src/views/dataset/Upload.vue
index 028b2d4f44..2fb2a1e4fe 100644
--- a/jena-fuseki2/jena-fuseki-ui/src/views/dataset/Upload.vue
+++ b/jena-fuseki2/jena-fuseki-ui/src/views/dataset/Upload.vue
@@ -60,7 +60,7 @@
placeholder="Leave blank for default graph"
/>
<div class="invalid-feedback">
- Invalid graph name. Please remove any spaces.
+ Invalid graph name. Please remove any spaces, and
provide a valid URI (RFC 3986).
</div>
</div>
</div>
@@ -221,6 +221,7 @@ import { FontAwesomeIcon } from
'@fortawesome/vue-fontawesome'
import currentDatasetMixin from '@/mixins/current-dataset'
import currentDatasetMixinNavigationGuards from
'@/mixins/current-dataset-navigation-guards'
import { displayError } from '@/utils'
+import { validateGraphName } from '@/utils/validation'
library.add(faPlus, faUpload, faTimesCircle, faMinusCircle)
@@ -418,15 +419,11 @@ export default {
return this.validateGraphName() && this.validateFiles()
},
validateGraphName () {
- // No spaces allowed in graph names.
- const pattern = /^[^\s]+$/
const graphName = this.$refs['dataset-graph-name'].value
- if (graphName === '' || pattern.test(graphName)) {
- this.graphNameClasses = ['form-control is-valid']
- return true
- }
- this.graphNameClasses = ['form-control is-invalid']
- return false
+ const isValidGraphName = validateGraphName(graphName)
+ const formValidationClass = isValidGraphName ? 'is-valid' : 'is-invalid'
+ this.graphNameClasses = ['form-control', formValidationClass]
+ return isValidGraphName
},
validateFiles () {
if (this.upload.files !== null && this.upload.files.length > 0) {
diff --git a/jena-fuseki2/jena-fuseki-ui/tests/unit/utils/validation.spec.js
b/jena-fuseki2/jena-fuseki-ui/tests/unit/utils/validation.spec.js
new file mode 100644
index 0000000000..89a6e98fd5
--- /dev/null
+++ b/jena-fuseki2/jena-fuseki-ui/tests/unit/utils/validation.spec.js
@@ -0,0 +1,84 @@
+/**
+ * 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.
+ */
+import { describe, expect, it } from 'vitest'
+import { validateGraphName } from '@/utils/validation'
+
+const VALID_GRAPH_NAMES = [
+ // From issue GH-2370 discussion
+ 'urn:x-arq:UnionGraph',
+ 'urn:x-arq:DefaultGraph',
+ 'urn:uuid:6e8bc430-9c3a-11d9-9669-0800200c9a66',
+ 'https://example.org/dataset',
+ 'https://example.org/dataset#graph',
+ 'https://example.org/dataset#graph?Aaa',
+ // From RFC-3986
+ 'ftp://ftp.is.co.za/rfc/rfc1808.txt',
+ 'http://www.ietf.org/rfc/rfc2396.txt',
+ 'ldap://[2001:db8::7]/c=GB?objectClass?one',
+ 'mailto:[email protected]',
+ 'news:comp.infosystems.www.servers.unix',
+ 'tel:+1-816-555-1212',
+ 'telnet://192.0.2.16:80/',
+ 'urn:oasis:names:specification:docbook:dtd:xml:4.1.2',
+ 'foo://example.com:8042/over/there?name=ferret#nose',
+ 'example://a/b/c/%7Bfoo%7D',
+ 'eXAMPLE://a/./b/../b/%63/%7bfoo%7d',
+ 'http://example.com:80/',
+ 'ftp://cnn.example.com&[email protected]/top_story.htm',
+ // From URI.js docs
+ 'uri://user:[email protected]:123/one/two.three?q1=a1&q2=a2#body',
+ 'HTTP://ABC.COM:80',
+ 'HTTPS://ABC.COM:443/',
+ 'WS://ABC.COM:80/chat#one',
+
'mailto:[email protected],[email protected]?subject=SUBSCRIBE&body=Sign%20me%20up!',
+ 'uri://www.example.org/red%09ros\xE9#red',
+ 'uri://www.example.org/red%09ros%C3%A9#red',
+ 'uri://www.example.org/D%C3%BCrst',
+ 'uri://www.example.org/D\xFCrst',
+ 'wss://example.com/foo?bar'
+]
+
+const INVALID_GRAPH_NAMES = [
+ // From issue GH-2370 discussion
+ 'snoopy',
+ 'test',
+ 'default',
+ 'wss://example.com/ foo?bar',
+ 'https://this is an invalid URL.com',
+ 'http%3A//www.example.com/other/graph'
+]
+
+describe('validation', () => {
+ it('Should reject empty graph names', () => {
+ expect(validateGraphName('')).to.equals(false)
+ expect(validateGraphName(' ')).to.equals(false)
+ })
+ it('Should reject graph names that contain spaces', () => {
+ expect(validateGraphName('jena graph')).to.equals(false)
+ expect(validateGraphName('')).to.equals(false)
+ })
+ it('Should reject graph names that are not valid URIs', () => {
+ for (let graphName of INVALID_GRAPH_NAMES) {
+ expect(validateGraphName(graphName)).to.equals(false)
+ }
+ })
+ it('Should accept valid graph names', () => {
+ for (let graphName of VALID_GRAPH_NAMES) {
+ expect(validateGraphName(graphName), `Rejected valid graph name
"${graphName}"`).to.equals(true)
+ }
+ })
+})