From 2aaac8122dbf5fb68f1db3ab0674f1b9b78835e9 Mon Sep 17 00:00:00 2001 From: EmilioTR Date: Thu, 27 Jun 2024 13:16:02 +0200 Subject: [PATCH 01/11] this solution should fix the index file problem --- .../AuthenticationMenu/LogoutButton.jsx | 1 + src/dataProvider/SparqlDataProvider.js | 16 +++++++++------- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/components/InteractionLayout/AuthenticationMenu/LogoutButton.jsx b/src/components/InteractionLayout/AuthenticationMenu/LogoutButton.jsx index bb4207f..72d3e38 100644 --- a/src/components/InteractionLayout/AuthenticationMenu/LogoutButton.jsx +++ b/src/components/InteractionLayout/AuthenticationMenu/LogoutButton.jsx @@ -23,6 +23,7 @@ const LogoutButton = forwardRef((props, ref) => { function handleLogout(event) { event.preventDefault(); if (isLoggedIn) { + redirect("/"); logout(); } else { redirect("/login"); diff --git a/src/dataProvider/SparqlDataProvider.js b/src/dataProvider/SparqlDataProvider.js index 99b8060..e4d2388 100644 --- a/src/dataProvider/SparqlDataProvider.js +++ b/src/dataProvider/SparqlDataProvider.js @@ -46,7 +46,7 @@ export default { handleComunicaContextCreation(query); if (query.sourcesIndex) { - const additionalSources = await addComunicaContextSourcesFromSourcesIndex(query.sourcesIndex); + const additionalSources = await addComunicaContextSourcesFromSourcesIndex(query); query.comunicaContext.sources = [...new Set([...query.comunicaContext.sources, ...additionalSources])]; } @@ -340,19 +340,22 @@ async function configureBindingStream(bindingStream, variables) { * @param {object} sourcesIndex - the sourcesIndex object as found in the configuration * @returns {array} array of sources found */ -const addComunicaContextSourcesFromSourcesIndex = async (sourcesIndex) => { +const addComunicaContextSourcesFromSourcesIndex = async (query) => { const sourcesList = []; try { let queryStringIndexSource; - if (sourcesIndex.queryLocation){ - const result = await fetch(`${config.queryFolder}${sourcesIndex.queryLocation}`); + if (query.sourcesIndex.queryLocation){ + const result = await fetch(`${config.queryFolder}${query.sourcesIndex.queryLocation}`); queryStringIndexSource = await result.text(); }else{ - queryStringIndexSource = sourcesIndex.queryString; + queryStringIndexSource = query.sourcesIndex.queryString; } + const queryForSourceRetrieval = query + queryForSourceRetrieval.comunicaContext.sources = [query.sourcesIndex.url] + const bindingsStream = await myEngine.queryBindings(queryStringIndexSource, { - sources: [sourcesIndex.url], + ...generateContext(queryForSourceRetrieval.comunicaContext), }); await new Promise((resolve, reject) => { @@ -381,7 +384,6 @@ const addComunicaContextSourcesFromSourcesIndex = async (sourcesIndex) => { return sourcesList; }; - /** * Creates/extends a comunicaContext property in a query * @param {object} query - the query element from the configuration From 22632d179a5dec65a0f3d46c689e160653f4e40f Mon Sep 17 00:00:00 2001 From: EmilioTR Date: Thu, 27 Jun 2024 13:40:36 +0200 Subject: [PATCH 02/11] fixed a little bug that added the Index Source Url to the comunica sources --- src/dataProvider/SparqlDataProvider.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/dataProvider/SparqlDataProvider.js b/src/dataProvider/SparqlDataProvider.js index e4d2388..217dee7 100644 --- a/src/dataProvider/SparqlDataProvider.js +++ b/src/dataProvider/SparqlDataProvider.js @@ -46,7 +46,7 @@ export default { handleComunicaContextCreation(query); if (query.sourcesIndex) { - const additionalSources = await addComunicaContextSourcesFromSourcesIndex(query); + const additionalSources = await addComunicaContextSourcesFromSourcesIndex(query.sourcesIndex); query.comunicaContext.sources = [...new Set([...query.comunicaContext.sources, ...additionalSources])]; } @@ -340,24 +340,24 @@ async function configureBindingStream(bindingStream, variables) { * @param {object} sourcesIndex - the sourcesIndex object as found in the configuration * @returns {array} array of sources found */ -const addComunicaContextSourcesFromSourcesIndex = async (query) => { +const addComunicaContextSourcesFromSourcesIndex = async (sourcesIndex) => { const sourcesList = []; try { let queryStringIndexSource; - if (query.sourcesIndex.queryLocation){ - const result = await fetch(`${config.queryFolder}${query.sourcesIndex.queryLocation}`); + if (sourcesIndex.queryLocation){ + const result = await fetch(`${config.queryFolder}${sourcesIndex.queryLocation}`); queryStringIndexSource = await result.text(); }else{ - queryStringIndexSource = query.sourcesIndex.queryString; + queryStringIndexSource = sourcesIndex.queryString; } - const queryForSourceRetrieval = query - queryForSourceRetrieval.comunicaContext.sources = [query.sourcesIndex.url] + // const queryForSourceRetrieval = query + // console.log(queryForSourceRetrieval) + // queryForSourceRetrieval.comunicaContext.sources = [query.sourcesIndex.url] const bindingsStream = await myEngine.queryBindings(queryStringIndexSource, { - ...generateContext(queryForSourceRetrieval.comunicaContext), + ...generateContext({sources: [sourcesIndex.url]}), }); - await new Promise((resolve, reject) => { bindingsStream.on('data', (bindings) => { // the bindings should have exactly one key (any name is allowed) and we accept the value as a source From 071192a6d124c5f7de187b669986a5db8bd4bff5 Mon Sep 17 00:00:00 2001 From: EmilioTR Date: Thu, 27 Jun 2024 13:41:12 +0200 Subject: [PATCH 03/11] update --- src/dataProvider/SparqlDataProvider.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/dataProvider/SparqlDataProvider.js b/src/dataProvider/SparqlDataProvider.js index 217dee7..7f7aab0 100644 --- a/src/dataProvider/SparqlDataProvider.js +++ b/src/dataProvider/SparqlDataProvider.js @@ -350,11 +350,7 @@ const addComunicaContextSourcesFromSourcesIndex = async (sourcesIndex) => { }else{ queryStringIndexSource = sourcesIndex.queryString; } - - // const queryForSourceRetrieval = query - // console.log(queryForSourceRetrieval) - // queryForSourceRetrieval.comunicaContext.sources = [query.sourcesIndex.url] - + const bindingsStream = await myEngine.queryBindings(queryStringIndexSource, { ...generateContext({sources: [sourcesIndex.url]}), }); From 3251b1140ea18ec68f2a1dcd26819f0eb0848a09 Mon Sep 17 00:00:00 2001 From: Martin Vanbrabant Date: Thu, 27 Jun 2024 15:44:52 +0200 Subject: [PATCH 04/11] Added index-example-texon-only-AUTH --- initial-pod-data/index-example-texon-only-AUTH.acl | 9 +++++++++ initial-pod-data/index-example-texon-only-AUTH.ttl | 7 +++++++ 2 files changed, 16 insertions(+) create mode 100644 initial-pod-data/index-example-texon-only-AUTH.acl create mode 100644 initial-pod-data/index-example-texon-only-AUTH.ttl diff --git a/initial-pod-data/index-example-texon-only-AUTH.acl b/initial-pod-data/index-example-texon-only-AUTH.acl new file mode 100644 index 0000000..7870088 --- /dev/null +++ b/initial-pod-data/index-example-texon-only-AUTH.acl @@ -0,0 +1,9 @@ +@prefix acl: . +@prefix foaf: . + +<#owner> + a acl:Authorization; + acl:accessTo <./index-example-texon-only>; + acl:agent ; + acl:mode acl:Read, acl:Write, acl:Control. + diff --git a/initial-pod-data/index-example-texon-only-AUTH.ttl b/initial-pod-data/index-example-texon-only-AUTH.ttl new file mode 100644 index 0000000..861e946 --- /dev/null +++ b/initial-pod-data/index-example-texon-only-AUTH.ttl @@ -0,0 +1,7 @@ +@prefix rdfs: . + +<#index-example> rdfs:seeAlso + , + , + +. From 95fb45447bbc57d0a9aa6f62ba091b1f10e3f47d Mon Sep 17 00:00:00 2001 From: EmilioTR Date: Thu, 27 Jun 2024 15:45:42 +0200 Subject: [PATCH 05/11] added a testcase --- src/config.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/config.json b/src/config.json index 6aaece5..34ea3d4 100644 --- a/src/config.json +++ b/src/config.json @@ -170,6 +170,18 @@ "queryLocation": "/sourceQueries/index_example_texon_only_source.rq" } }, + { + "id": "1500", + "queryGroupId": "c-tst", + "queryLocation": "components_materials.rq", + "name": "Sources from an index file (requiring authentication)", + "description": "Query components (including details about materials) with the sources obtained from index files that require authentication to retrieve said sources.", + "sourcesIndex": { + "url": "http://localhost:8080/example/index-example-texon-only-AUTH", + "queryLocation": "/sourceQueries/index_example_texon_only_source.rq" + } + }, + { "id": "2000", "queryGroupId": "b-prj", From 288a931a80846a6ef8307fa03453a06977aff73b Mon Sep 17 00:00:00 2001 From: Martin Vanbrabant Date: Thu, 27 Jun 2024 16:07:01 +0200 Subject: [PATCH 06/11] file needs $ at the end --- ...ple-texon-only-AUTH.ttl => index-example-texon-only-AUTH$.ttl} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename initial-pod-data/{index-example-texon-only-AUTH.ttl => index-example-texon-only-AUTH$.ttl} (100%) diff --git a/initial-pod-data/index-example-texon-only-AUTH.ttl b/initial-pod-data/index-example-texon-only-AUTH$.ttl similarity index 100% rename from initial-pod-data/index-example-texon-only-AUTH.ttl rename to initial-pod-data/index-example-texon-only-AUTH$.ttl From 8bf930bd86d9ac38388da68426ec3c623a644f72 Mon Sep 17 00:00:00 2001 From: Martin Vanbrabant Date: Thu, 27 Jun 2024 16:16:38 +0200 Subject: [PATCH 07/11] corrected acl:accessTo --- initial-pod-data/index-example-texon-only-AUTH.acl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/initial-pod-data/index-example-texon-only-AUTH.acl b/initial-pod-data/index-example-texon-only-AUTH.acl index 7870088..5f4d464 100644 --- a/initial-pod-data/index-example-texon-only-AUTH.acl +++ b/initial-pod-data/index-example-texon-only-AUTH.acl @@ -3,7 +3,7 @@ <#owner> a acl:Authorization; - acl:accessTo <./index-example-texon-only>; + acl:accessTo <./index-example-texon-only-AUTH>; acl:agent ; acl:mode acl:Read, acl:Write, acl:Control. From f45a55df16f994717c342b9b878be57f2cac704f Mon Sep 17 00:00:00 2001 From: EmilioTR Date: Thu, 27 Jun 2024 16:23:44 +0200 Subject: [PATCH 08/11] added a query for index file --- .../index_example_texon_required_authentication.rq | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 public/queries/sourceQueries/index_example_texon_required_authentication.rq diff --git a/public/queries/sourceQueries/index_example_texon_required_authentication.rq b/public/queries/sourceQueries/index_example_texon_required_authentication.rq new file mode 100644 index 0000000..927c065 --- /dev/null +++ b/public/queries/sourceQueries/index_example_texon_required_authentication.rq @@ -0,0 +1,8 @@ +PREFIX rdf: +PREFIX rdfs: +PREFIX example: + +SELECT ?object +WHERE { + example:index-example rdfs:seeAlso ?object . +} From ac914036ca189e9b4360aeb805b51356b1736fd9 Mon Sep 17 00:00:00 2001 From: EmilioTR Date: Thu, 27 Jun 2024 16:28:18 +0200 Subject: [PATCH 09/11] fixed --- src/config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config.json b/src/config.json index 34ea3d4..a2af19e 100644 --- a/src/config.json +++ b/src/config.json @@ -178,7 +178,7 @@ "description": "Query components (including details about materials) with the sources obtained from index files that require authentication to retrieve said sources.", "sourcesIndex": { "url": "http://localhost:8080/example/index-example-texon-only-AUTH", - "queryLocation": "/sourceQueries/index_example_texon_only_source.rq" + "queryLocation": "/sourceQueries/index_example_texon_required_authentication.rq" } }, From 73b712d436e2f58bc9e9cd144eb1366d4da73d63 Mon Sep 17 00:00:00 2001 From: Martin Vanbrabant Date: Thu, 27 Jun 2024 16:45:35 +0200 Subject: [PATCH 10/11] Updated CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d4065b1..e802ba0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Forced CSS's to not return content type application/ld+json, which induced a CORS error on some CSS server versions (#131). - Queries based on index file now work for any variable, not just ?object (#136). +- Queries based on index file now work for index files requiring authentication (#139). ## [1.2.1] - 2024-06-17 From 5db57b1d2aaaa578056b078735bef938929f1a3c Mon Sep 17 00:00:00 2001 From: EmilioTR Date: Thu, 27 Jun 2024 16:56:19 +0200 Subject: [PATCH 11/11] added a test for restricted index sources --- cypress/e2e/sources-from-indexfile.cy.js | 53 +++++++++++++++++-- ...> index_example_texon_only_source_AUTH.rq} | 0 src/config.json | 2 +- 3 files changed, 51 insertions(+), 4 deletions(-) rename public/queries/sourceQueries/{index_example_texon_required_authentication.rq => index_example_texon_only_source_AUTH.rq} (100%) diff --git a/cypress/e2e/sources-from-indexfile.cy.js b/cypress/e2e/sources-from-indexfile.cy.js index 548d8d0..962ed0e 100644 --- a/cypress/e2e/sources-from-indexfile.cy.js +++ b/cypress/e2e/sources-from-indexfile.cy.js @@ -12,7 +12,7 @@ describe("Sources from index file", () => { // Check that it indeed had 3 sources cy.get('.information-box').contains('Sources: 3'); - + // Check if correct data is displayed cy.contains("http://www/example.com/data/component-c01"); cy.contains("Component 1"); @@ -31,7 +31,7 @@ describe("Sources from index file", () => { // Check that all 4 sources were used cy.get('.information-box').contains('Sources: 4'); - + // Check if correct data is still displayed even if one source was unauthorized cy.contains("http://www/example.com/data/component-c01"); cy.contains("Component 1"); @@ -50,11 +50,58 @@ describe("Sources from index file", () => { // Check that the 4 sources were successfully merged cy.get('.information-box').contains('Sources: 4'); - + // Check if correct data is still displayed even if one source was unauthorized and different sources were merged cy.contains("http://www/example.com/data/component-c01"); cy.contains("Component 1"); cy.contains("Material 1"); }); + it("Sources from an unauthorized source. Before and after log in.", () => { + cy.visit("/"); + + cy.intercept('GET', 'http://localhost:8080/example/index-example-texon-only-AUTH').as('getRequest'); + + // Navigate to correct query + cy.contains("For testing only").click(); + cy.contains("Sources from an index file (requiring authentication)").click(); + + // Wait for the request and assert the response + cy.wait('@getRequest').then((interception) => { + expect(interception.response.statusCode).to.equal(401); + }); + + + cy.contains("http://www/example.com/data/component-c01").should("not.exist"); + cy.contains("Component 1").should("not.exist"); + cy.contains("Material 1").should("not.exist"); + + //log in + cy.get('[aria-label="Profile"]').click(); + cy.contains('[role="menuitem"]', "Login").click(); + + cy.get('input[name="idp"]') + .clear(); + cy.get('input[name="idp"]') + .type("http://localhost:8080/example/profile/card#me"); + cy.contains("Login").click(); + + cy.get("input#email").type("hello@example.com"); + cy.get("input#password").type("abc123"); + cy.contains("button", "Log in").click(); + cy.contains("button", "Authorize").click(); + + cy.url().should("eq", "http://localhost:5173/"); + + //now try again + cy.contains("For testing only").click(); + cy.contains("Sources from an index file (requiring authentication)").click(); + + cy.contains("http://www/example.com/data/component-c01").should("not.exist"); + cy.contains("Component 1").should("exist"); + cy.contains("Material 1").should("exist"); + }) + + + }); diff --git a/public/queries/sourceQueries/index_example_texon_required_authentication.rq b/public/queries/sourceQueries/index_example_texon_only_source_AUTH.rq similarity index 100% rename from public/queries/sourceQueries/index_example_texon_required_authentication.rq rename to public/queries/sourceQueries/index_example_texon_only_source_AUTH.rq diff --git a/src/config.json b/src/config.json index a2af19e..746e247 100644 --- a/src/config.json +++ b/src/config.json @@ -178,7 +178,7 @@ "description": "Query components (including details about materials) with the sources obtained from index files that require authentication to retrieve said sources.", "sourcesIndex": { "url": "http://localhost:8080/example/index-example-texon-only-AUTH", - "queryLocation": "/sourceQueries/index_example_texon_required_authentication.rq" + "queryLocation": "/sourceQueries/index_example_texon_only_source_AUTH.rq" } },