From abd544641e8b29ed3e0e4703d3049c1956449c2e Mon Sep 17 00:00:00 2001 From: surilindur Date: Fri, 12 Aug 2022 00:25:04 +0300 Subject: [PATCH 1/8] added initial tests for non-existing resources --- .../read-access-agent.feature | 28 +++++++++++++++++-- .../read-access-bob.feature | 28 +++++++++++++++++-- .../read-access-public.feature | 28 +++++++++++++++++-- .../read-inherited-access-agent.feature | 25 ++++++++++++++++- .../read-inherited-access-bob.feature | 25 ++++++++++++++++- .../read-inherited-access-public.feature | 25 ++++++++++++++++- 6 files changed, 150 insertions(+), 9 deletions(-) diff --git a/web-access-control/protected-operation/read-access-agent.feature b/web-access-control/protected-operation/read-access-agent.feature index 0e90ccd..3f6e215 100644 --- a/web-access-control/protected-operation/read-access-agent.feature +++ b/web-access-control/protected-operation/read-access-agent.feature @@ -9,14 +9,16 @@ Feature: Only authenticated agents can read (and only that) a resource when gran function (modes) { const testContainer = rootTestContainer.createContainer() testContainer.accessDataset = testContainer.accessDatasetBuilder - .setAuthenticatedAccess(testContainer.url, ['read', 'write', 'append', 'control']).build() + .setAuthenticatedAccess(testContainer.url, ['read', 'write', 'append', 'control']) + .setInheritableAuthenticatedAccess(testContainer.url, modes).build() const plainResource = testContainer.createResource('.txt', 'Hello', 'text/plain') plainResource.accessDataset = plainResource.accessDatasetBuilder.setAuthenticatedAccess(plainResource.url, modes).build() + const fictiveResource = testContainer.reserveResource('.txt') const rdfResource = testContainer.createResource('.ttl', karate.readAsString('../fixtures/example.ttl'), 'text/turtle') rdfResource.accessDataset = rdfResource.accessDatasetBuilder.setAuthenticatedAccess(rdfResource.url, modes).build() const container = testContainer.createContainer() container.accessDataset = container.accessDatasetBuilder.setAuthenticatedAccess(container.url, modes).build() - return { plain: plainResource, rdf: rdfResource, container: container } + return { plain: plainResource, fictive: fictiveResource, rdf: rdfResource, container: container } } """ # Create 3 test resources with read access for authenticated agents @@ -32,27 +34,35 @@ Feature: Only authenticated agents can read (and only that) a resource when gran Examples: | agent | type | mode | method | public! | status | | Bob can | plain | R | GET | false | 200 | + | Bob can | fictive | R | GET | false | 404 | | Bob can | rdf | R | GET | false | 200 | | Bob can | container | R | GET | false | 200 | | Bob can | plain | R | HEAD | false | 200 | + | Bob can | fictive | R | HEAD | false | 404 | | Bob can | rdf | R | HEAD | false | 200 | | Bob can | container | R | HEAD | false | 200 | | Public cannot | plain | R | GET | true | 401 | + | Public cannot | fictive | R | GET | true | 401 | | Public cannot | rdf | R | GET | true | 401 | | Public cannot | container | R | GET | true | 401 | | Public cannot | plain | R | HEAD | true | 401 | + | Public cannot | fictive | R | HEAD | true | 401 | | Public cannot | rdf | R | HEAD | true | 401 | | Public cannot | container | R | HEAD | true | 401 | | Bob cannot | plain | AWC | GET | false | 403 | + | Bob cannot | fictive | AWC | GET | false | 403 | | Bob cannot | rdf | AWC | GET | false | 403 | | Bob cannot | container | AWC | GET | false | 403 | | Bob cannot | plain | AWC | HEAD | false | 403 | + | Bob cannot | fictive | AWC | HEAD | false | 403 | | Bob cannot | rdf | AWC | HEAD | false | 403 | | Bob cannot | container | AWC | HEAD | false | 403 | | Public cannot | plain | AWC | GET | true | 401 | + | Public cannot | fictive | AWC | GET | true | 401 | | Public cannot | rdf | AWC | GET | true | 401 | | Public cannot | container | AWC | GET | true | 401 | | Public cannot | plain | AWC | HEAD | true | 401 | + | Public cannot | fictive | AWC | HEAD | true | 401 | | Public cannot | rdf | AWC | HEAD | true | 401 | | Public cannot | container | AWC | HEAD | true | 401 | @@ -66,12 +76,16 @@ Feature: Only authenticated agents can read (and only that) a resource when gran Examples: | agent | type | mode | method | public! | status | | Bob | rdf | R | PUT | false | 403 | + | Bob | fictive | R | PUT | false | 403 | | Bob | container | R | PUT | false | 403 | | Bob | rdf | R | POST | false | 403 | + | Bob | fictive | R | POST | false | 404 | | Bob | container | R | POST | false | 403 | | Public | rdf | R | PUT | true | 401 | + | Public | fictive | R | PUT | true | 401 | | Public | container | R | PUT | true | 401 | | Public | rdf | R | POST | true | 401 | + | Public | fictive | R | POST | true | 401 | | Public | container | R | POST | true | 401 | Scenario Outline: cannot to a resource to which an authenticated agent has access @@ -84,8 +98,10 @@ Feature: Only authenticated agents can read (and only that) a resource when gran Examples: | agent | type | mode | method | public! | status | | Bob | rdf | R | PATCH | false | 403 | + | Bob | fictive | R | PATCH | false | 403 | | Bob | container | R | PATCH | false | 403 | | Public | rdf | R | PATCH | true | 401 | + | Public | fictive | R | PATCH | true | 401 | | Public | container | R | PATCH | true | 401 | Scenario Outline: cannot to a resource to which an authenticated agent has access @@ -100,9 +116,15 @@ Feature: Only authenticated agents can read (and only that) a resource when gran | Bob | plain | R | PUT | false | [403] | | Bob | plain | R | POST | false | [403] | | Bob | plain | R | PATCH | false | [403, 405, 415] | + | Bob | fictive | R | PUT | false | [403] | + | Bob | fictive | R | POST | false | [404] | + | Bob | fictive | R | PATCH | false | [403, 405, 415] | | Public | plain | R | PUT | true | [401] | | Public | plain | R | POST | true | [401] | | Public | plain | R | PATCH | true | [401, 405, 415] | + | Public | fictive | R | PUT | true | [401] | + | Public | fictive | R | POST | true | [401] | + | Public | fictive | R | PATCH | true | [401, 405, 415] | Scenario Outline: cannot a resource to which an authenticated agent has access Given url tests[type].url @@ -112,8 +134,10 @@ Feature: Only authenticated agents can read (and only that) a resource when gran Examples: | agent | type | mode | method | public! | status | | Bob | plain | R | DELETE | false | 403 | + | Bob | fictive | R | DELETE | false | 404 | | Bob | rdf | R | DELETE | false | 403 | | Bob | container | R | DELETE | false | 403 | | Public | plain | R | DELETE | true | 401 | + | Public | fictive | R | DELETE | true | 401 | | Public | rdf | R | DELETE | true | 401 | | Public | container | R | DELETE | true | 401 | diff --git a/web-access-control/protected-operation/read-access-bob.feature b/web-access-control/protected-operation/read-access-bob.feature index b0f75a2..cbe7e35 100644 --- a/web-access-control/protected-operation/read-access-bob.feature +++ b/web-access-control/protected-operation/read-access-bob.feature @@ -9,14 +9,16 @@ Feature: Only Bob can read (and only that) a resource when granted read access function (modes) { const testContainer = rootTestContainer.createContainer() testContainer.accessDataset = testContainer.accessDatasetBuilder - .setAgentAccess(testContainer.url, webIds.bob, ['read', 'write', 'append', 'control']).build() + .setAgentAccess(testContainer.url, webIds.bob, ['read', 'write', 'append', 'control']) + .setInheritableAgentAccess(testContainer.url, webIds.bob, modes).build() const plainResource = testContainer.createResource('.txt', 'Hello', 'text/plain') plainResource.accessDataset = plainResource.accessDatasetBuilder.setAgentAccess(plainResource.url, webIds.bob, modes).build() + const fictiveResource = testContainer.reserveResource('.txt') const rdfResource = testContainer.createResource('.ttl', karate.readAsString('../fixtures/example.ttl'), 'text/turtle') rdfResource.accessDataset = rdfResource.accessDatasetBuilder.setAgentAccess(rdfResource.url, webIds.bob, modes).build() const container = testContainer.createContainer() container.accessDataset = container.accessDatasetBuilder.setAgentAccess(container.url, webIds.bob, modes).build() - return { plain: plainResource, rdf: rdfResource, container: container } + return { plain: plainResource, fictive: fictiveResource, rdf: rdfResource, container: container } } """ # Create 3 test resources with read access for Bob @@ -32,27 +34,35 @@ Feature: Only Bob can read (and only that) a resource when granted read access Examples: | agent | type | mode | method | public! | status | | Bob can | plain | R | GET | false | 200 | + | Bob can | fictive | R | GET | false | 404 | | Bob can | rdf | R | GET | false | 200 | | Bob can | container | R | GET | false | 200 | | Bob can | plain | R | HEAD | false | 200 | + | Bob can | fictive | R | HEAD | false | 404 | | Bob can | rdf | R | HEAD | false | 200 | | Bob can | container | R | HEAD | false | 200 | | Public cannot | plain | R | GET | true | 401 | + | Public cannot | fictive | R | GET | true | 401 | | Public cannot | rdf | R | GET | true | 401 | | Public cannot | container | R | GET | true | 401 | | Public cannot | plain | R | HEAD | true | 401 | + | Public cannot | fictive | R | HEAD | true | 401 | | Public cannot | rdf | R | HEAD | true | 401 | | Public cannot | container | R | HEAD | true | 401 | | Bob cannot | plain | AWC | GET | false | 403 | + | Bob cannot | fictive | AWC | GET | false | 403 | | Bob cannot | rdf | AWC | GET | false | 403 | | Bob cannot | container | AWC | GET | false | 403 | | Bob cannot | plain | AWC | HEAD | false | 403 | + | Bob cannot | fictive | AWC | HEAD | false | 403 | | Bob cannot | rdf | AWC | HEAD | false | 403 | | Bob cannot | container | AWC | HEAD | false | 403 | | Public cannot | plain | AWC | GET | true | 401 | + | Public cannot | fictive | AWC | GET | true | 401 | | Public cannot | rdf | AWC | GET | true | 401 | | Public cannot | container | AWC | GET | true | 401 | | Public cannot | plain | AWC | HEAD | true | 401 | + | Public cannot | fictive | AWC | HEAD | true | 401 | | Public cannot | rdf | AWC | HEAD | true | 401 | | Public cannot | container | AWC | HEAD | true | 401 | @@ -66,12 +76,16 @@ Feature: Only Bob can read (and only that) a resource when granted read access Examples: | agent | type | mode | method | public! | status | | Bob | rdf | R | PUT | false | 403 | + | Bob | fictive | R | PUT | false | 403 | | Bob | container | R | PUT | false | 403 | | Bob | rdf | R | POST | false | 403 | + | Bob | fictive | R | POST | false | 404 | | Bob | container | R | POST | false | 403 | | Public | rdf | R | PUT | true | 401 | + | Public | fictive | R | PUT | true | 401 | | Public | container | R | PUT | true | 401 | | Public | rdf | R | POST | true | 401 | + | Public | fictive | R | POST | true | 401 | | Public | container | R | POST | true | 401 | Scenario Outline: cannot to a resource to which Bob has access @@ -84,8 +98,10 @@ Feature: Only Bob can read (and only that) a resource when granted read access Examples: | agent | type | mode | method | public! | status | | Bob | rdf | R | PATCH | false | 403 | + | Bob | fictive | R | PATCH | false | 403 | | Bob | container | R | PATCH | false | 403 | | Public | rdf | R | PATCH | true | 401 | + | Public | fictive | R | PATCH | true | 401 | | Public | container | R | PATCH | true | 401 | Scenario Outline: cannot to a resource to which Bob has access @@ -100,9 +116,15 @@ Feature: Only Bob can read (and only that) a resource when granted read access | Bob | plain | R | PUT | false | [403] | | Bob | plain | R | POST | false | [403] | | Bob | plain | R | PATCH | false | [403, 405, 415] | + | Bob | fictive | R | PUT | false | [403] | + | Bob | fictive | R | POST | false | [404] | + | Bob | fictive | R | PATCH | false | [403, 405, 415] | | Public | plain | R | PUT | true | [401] | | Public | plain | R | POST | true | [401] | | Public | plain | R | PATCH | true | [401, 405, 415] | + | Public | fictive | R | PUT | true | [401] | + | Public | fictive | R | POST | true | [401] | + | Public | fictive | R | PATCH | true | [401, 405, 415] | Scenario Outline: cannot a resource to which Bob has access Given url tests[type].url @@ -112,8 +134,10 @@ Feature: Only Bob can read (and only that) a resource when granted read access Examples: | agent | type | mode | method | public! | status | | Bob | plain | R | DELETE | false | 403 | + | Bob | fictive | R | DELETE | false | 404 | | Bob | rdf | R | DELETE | false | 403 | | Bob | container | R | DELETE | false | 403 | | Public | plain | R | DELETE | true | 401 | + | Public | fictive | R | DELETE | true | 401 | | Public | rdf | R | DELETE | true | 401 | | Public | container | R | DELETE | true | 401 | diff --git a/web-access-control/protected-operation/read-access-public.feature b/web-access-control/protected-operation/read-access-public.feature index 31eda78..7d2d7d6 100644 --- a/web-access-control/protected-operation/read-access-public.feature +++ b/web-access-control/protected-operation/read-access-public.feature @@ -9,14 +9,16 @@ Feature: Public agents can read (and only that) a resource when granted read acc function (modes) { const testContainer = rootTestContainer.createContainer() testContainer.accessDataset = testContainer.accessDatasetBuilder - .setPublicAccess(testContainer.url, ['read', 'write', 'append', 'control']).build() + .setPublicAccess(testContainer.url, ['read', 'write', 'append', 'control']) + .setInheritablePublicAccess(testContainer.url, modes).build() const plainResource = testContainer.createResource('.txt', 'Hello', 'text/plain') plainResource.accessDataset = plainResource.accessDatasetBuilder.setPublicAccess(plainResource.url, modes).build() + const fictiveResource = testContainer.reserveResource('.txt') const rdfResource = testContainer.createResource('.ttl', karate.readAsString('../fixtures/example.ttl'), 'text/turtle') rdfResource.accessDataset = rdfResource.accessDatasetBuilder.setPublicAccess(rdfResource.url, modes).build() const container = testContainer.createContainer() container.accessDataset = container.accessDatasetBuilder.setPublicAccess(container.url, modes).build() - return { plain: plainResource, rdf: rdfResource, container: container } + return { plain: plainResource, fictive: fictiveResource, rdf: rdfResource, container: container } } """ # Create 3 test resources with read access for public agents @@ -32,21 +34,27 @@ Feature: Public agents can read (and only that) a resource when granted read acc Examples: | agent | type | mode | method | public! | status | | Bob can | plain | R | GET | false | 200 | + | Bob can | fictive | R | GET | false | 404 | | Bob can | rdf | R | GET | false | 200 | | Bob can | container | R | GET | false | 200 | | Bob can | plain | R | HEAD | false | 200 | + | Bob can | fictive | R | HEAD | false | 404 | | Bob can | rdf | R | HEAD | false | 200 | | Bob can | container | R | HEAD | false | 200 | | Bob cannot | plain | AWC | GET | false | 403 | + | Bob cannot | fictive | AWC | GET | false | 403 | | Bob cannot | rdf | AWC | GET | false | 403 | | Bob cannot | container | AWC | GET | false | 403 | | Bob cannot | plain | AWC | HEAD | false | 403 | + | Bob cannot | fictive | AWC | HEAD | false | 403 | | Bob cannot | rdf | AWC | HEAD | false | 403 | | Bob cannot | container | AWC | HEAD | false | 403 | | Public cannot | plain | AWC | GET | true | 401 | + | Public cannot | fictive | AWC | GET | true | 401 | | Public cannot | rdf | AWC | GET | true | 401 | | Public cannot | container | AWC | GET | true | 401 | | Public cannot | plain | AWC | HEAD | true | 401 | + | Public cannot | fictive | AWC | HEAD | true | 401 | | Public cannot | rdf | AWC | HEAD | true | 401 | | Public cannot | container | AWC | HEAD | true | 401 | @@ -54,9 +62,11 @@ Feature: Public agents can read (and only that) a resource when granted read acc Examples: | agent | type | mode | method | public! | status | | Public can | plain | R | GET | true | 200 | + | Public can | fictive | R | GET | true | 404 | | Public can | rdf | R | GET | true | 200 | | Public can | container | R | GET | true | 200 | | Public can | plain | R | HEAD | true | 200 | + | Public can | fictive | R | HEAD | true | 404 | | Public can | rdf | R | HEAD | true | 200 | | Public can | container | R | HEAD | true | 200 | @@ -70,12 +80,16 @@ Feature: Public agents can read (and only that) a resource when granted read acc Examples: | agent | type | mode | method | public! | status | | Bob | rdf | R | PUT | false | 403 | + | Bob | fictive | R | PUT | false | 403 | | Bob | container | R | PUT | false | 403 | | Bob | rdf | R | POST | false | 403 | + | Bob | fictive | R | POST | false | 404 | | Bob | container | R | POST | false | 403 | | Public | rdf | R | PUT | true | 401 | + | Public | fictive | R | PUT | true | 401 | | Public | container | R | PUT | true | 401 | | Public | rdf | R | POST | true | 401 | + | Public | fictive | R | POST | true | 404 | | Public | container | R | POST | true | 401 | Scenario Outline: cannot to a resource to which a public agent has access @@ -88,8 +102,10 @@ Feature: Public agents can read (and only that) a resource when granted read acc Examples: | agent | type | mode | method | public! | status | | Bob | rdf | R | PATCH | false | 403 | + | Bob | fictive | R | PATCH | false | 403 | | Bob | container | R | PATCH | false | 403 | | Public | rdf | R | PATCH | true | 401 | + | Public | fictive | R | PATCH | true | 401 | | Public | container | R | PATCH | true | 401 | Scenario Outline: cannot to a resource to which a public agent has access @@ -104,9 +120,15 @@ Feature: Public agents can read (and only that) a resource when granted read acc | Bob | plain | R | PUT | false | [403] | | Bob | plain | R | POST | false | [403] | | Bob | plain | R | PATCH | false | [403, 405, 415] | + | Bob | fictive | R | PUT | false | [403] | + | Bob | fictive | R | POST | false | [404] | + | Bob | fictive | R | PATCH | false | [403, 405, 415] | | Public | plain | R | PUT | true | [401] | | Public | plain | R | POST | true | [401] | | Public | plain | R | PATCH | true | [401, 405, 415] | + | Public | fictive | R | PUT | true | [401] | + | Public | fictive | R | POST | true | [404] | + | Public | fictive | R | PATCH | true | [401, 405, 415] | Scenario Outline: cannot a resource to which a public agent has access Given url tests[type].url @@ -116,8 +138,10 @@ Feature: Public agents can read (and only that) a resource when granted read acc Examples: | agent | type | mode | method | public! | status | | Bob | plain | R | DELETE | false | 403 | + | Bob | fictive | R | DELETE | false | 404 | | Bob | rdf | R | DELETE | false | 403 | | Bob | container | R | DELETE | false | 403 | | Public | plain | R | DELETE | true | 401 | + | Public | fictive | R | DELETE | true | 404 | | Public | rdf | R | DELETE | true | 401 | | Public | container | R | DELETE | true | 401 | diff --git a/web-access-control/protected-operation/read-inherited-access-agent.feature b/web-access-control/protected-operation/read-inherited-access-agent.feature index a6f85e0..e02427b 100644 --- a/web-access-control/protected-operation/read-inherited-access-agent.feature +++ b/web-access-control/protected-operation/read-inherited-access-agent.feature @@ -12,9 +12,10 @@ Feature: Only authenticated agents can read (and only that) a resource when gran .setAuthenticatedAccess(testContainer.url, ['read', 'write', 'append', 'control']) .setInheritableAuthenticatedAccess(testContainer.url, modes).build() const plainResource = testContainer.createResource('.txt', 'Hello', 'text/plain') + const fictiveResource = testContainer.reserveResource('.txt') const rdfResource = testContainer.createResource('.ttl', karate.readAsString('../fixtures/example.ttl'), 'text/turtle') const container = testContainer.createContainer() - return { plain: plainResource, rdf: rdfResource, container: container } + return { plain: plainResource, fictive: fictiveResource, rdf: rdfResource, container: container } } """ # Create 3 test resources with read access for authenticated agents @@ -30,27 +31,35 @@ Feature: Only authenticated agents can read (and only that) a resource when gran Examples: | agent | type | mode | method | public! | status | | Bob can | plain | R | GET | false | 200 | + | Bob can | fictive | R | GET | false | 404 | | Bob can | rdf | R | GET | false | 200 | | Bob can | container | R | GET | false | 200 | | Bob can | plain | R | HEAD | false | 200 | + | Bob can | fictive | R | HEAD | false | 404 | | Bob can | rdf | R | HEAD | false | 200 | | Bob can | container | R | HEAD | false | 200 | | Public cannot | plain | R | GET | true | 401 | + | Public cannot | fictive | R | GET | true | 401 | | Public cannot | rdf | R | GET | true | 401 | | Public cannot | container | R | GET | true | 401 | | Public cannot | plain | R | HEAD | true | 401 | + | Public cannot | fictive | R | HEAD | true | 401 | | Public cannot | rdf | R | HEAD | true | 401 | | Public cannot | container | R | HEAD | true | 401 | | Bob cannot | plain | AWC | GET | false | 403 | + | Bob cannot | fictive | AWC | GET | false | 403 | | Bob cannot | rdf | AWC | GET | false | 403 | | Bob cannot | container | AWC | GET | false | 403 | | Bob cannot | plain | AWC | HEAD | false | 403 | + | Bob cannot | fictive | AWC | HEAD | false | 403 | | Bob cannot | rdf | AWC | HEAD | false | 403 | | Bob cannot | container | AWC | HEAD | false | 403 | | Public cannot | plain | AWC | GET | true | 401 | + | Public cannot | fictive | AWC | GET | true | 401 | | Public cannot | rdf | AWC | GET | true | 401 | | Public cannot | container | AWC | GET | true | 401 | | Public cannot | plain | AWC | HEAD | true | 401 | + | Public cannot | fictive | AWC | HEAD | true | 401 | | Public cannot | rdf | AWC | HEAD | true | 401 | | Public cannot | container | AWC | HEAD | true | 401 | @@ -64,12 +73,16 @@ Feature: Only authenticated agents can read (and only that) a resource when gran Examples: | agent | type | mode | method | public! | status | | Bob | rdf | R | PUT | false | 403 | + | Bob | fictive | R | PUT | false | 403 | | Bob | container | R | PUT | false | 403 | | Bob | rdf | R | POST | false | 403 | + | Bob | fictive | R | POST | false | 404 | | Bob | container | R | POST | false | 403 | | Public | rdf | R | PUT | true | 401 | + | Public | fictive | R | PUT | true | 401 | | Public | container | R | PUT | true | 401 | | Public | rdf | R | POST | true | 401 | + | Public | fictive | R | POST | true | 401 | | Public | container | R | POST | true | 401 | Scenario Outline: cannot to a resource to which an authenticated agent has inherited access @@ -82,8 +95,10 @@ Feature: Only authenticated agents can read (and only that) a resource when gran Examples: | agent | type | mode | method | public! | status | | Bob | rdf | R | PATCH | false | 403 | + | Bob | fictive | R | PATCH | false | 403 | | Bob | container | R | PATCH | false | 403 | | Public | rdf | R | PATCH | true | 401 | + | Public | fictive | R | PATCH | true | 401 | | Public | container | R | PATCH | true | 401 | Scenario Outline: cannot to a resource to which an authenticated agent has inherited access @@ -98,9 +113,15 @@ Feature: Only authenticated agents can read (and only that) a resource when gran | Bob | plain | R | PUT | false | [403] | | Bob | plain | R | POST | false | [403] | | Bob | plain | R | PATCH | false | [403, 405, 415] | + | Bob | fictive | R | PUT | false | [403] | + | Bob | fictive | R | POST | false | [404] | + | Bob | fictive | R | PATCH | false | [403, 405, 415] | | Public | plain | R | PUT | true | [401] | | Public | plain | R | POST | true | [401] | | Public | plain | R | PATCH | true | [401, 405, 415] | + | Public | fictive | R | PUT | true | [401] | + | Public | fictive | R | POST | true | [401] | + | Public | fictive | R | PATCH | true | [401, 405, 415] | Scenario Outline: cannot a resource to which an authenticated agent has inherited access Given url tests[type].url @@ -110,8 +131,10 @@ Feature: Only authenticated agents can read (and only that) a resource when gran Examples: | agent | type | mode | method | public! | status | | Bob | plain | R | DELETE | false | 403 | + | Bob | fictive | R | DELETE | false | 404 | | Bob | rdf | R | DELETE | false | 403 | | Bob | container | R | DELETE | false | 403 | | Public | plain | R | DELETE | true | 401 | + | Public | fictive | R | DELETE | true | 401 | | Public | rdf | R | DELETE | true | 401 | | Public | container | R | DELETE | true | 401 | diff --git a/web-access-control/protected-operation/read-inherited-access-bob.feature b/web-access-control/protected-operation/read-inherited-access-bob.feature index 1298968..e0ac07f 100644 --- a/web-access-control/protected-operation/read-inherited-access-bob.feature +++ b/web-access-control/protected-operation/read-inherited-access-bob.feature @@ -12,9 +12,10 @@ Feature: Only Bob can read (and only that) a resource when granted inherited rea .setAgentAccess(testContainer.url, webIds.bob, ['read', 'write', 'append', 'control']) .setInheritableAgentAccess(testContainer.url, webIds.bob, modes).build() const plainResource = testContainer.createResource('.txt', 'Hello', 'text/plain') + const fictiveResource = testContainer.reserveResource('.txt') const rdfResource = testContainer.createResource('.ttl', karate.readAsString('../fixtures/example.ttl'), 'text/turtle') const container = testContainer.createContainer() - return { plain: plainResource, rdf: rdfResource, container: container } + return { plain: plainResource, fictive: fictiveResource, rdf: rdfResource, container: container } } """ # Create 3 test resources with read access for Bob @@ -30,27 +31,35 @@ Feature: Only Bob can read (and only that) a resource when granted inherited rea Examples: | agent | type | mode | method | public! | status | | Bob can | plain | R | GET | false | 200 | + | Bob can | fictive | R | GET | false | 404 | | Bob can | rdf | R | GET | false | 200 | | Bob can | container | R | GET | false | 200 | | Bob can | plain | R | HEAD | false | 200 | + | Bob can | fictive | R | HEAD | false | 404 | | Bob can | rdf | R | HEAD | false | 200 | | Bob can | container | R | HEAD | false | 200 | | Public cannot | plain | R | GET | true | 401 | + | Public cannot | fictive | R | GET | true | 401 | | Public cannot | rdf | R | GET | true | 401 | | Public cannot | container | R | GET | true | 401 | | Public cannot | plain | R | HEAD | true | 401 | + | Public cannot | fictive | R | HEAD | true | 401 | | Public cannot | rdf | R | HEAD | true | 401 | | Public cannot | container | R | HEAD | true | 401 | | Bob cannot | plain | AWC | GET | false | 403 | + | Bob cannot | fictive | AWC | GET | false | 403 | | Bob cannot | rdf | AWC | GET | false | 403 | | Bob cannot | container | AWC | GET | false | 403 | | Bob cannot | plain | AWC | HEAD | false | 403 | + | Bob cannot | fictive | AWC | HEAD | false | 403 | | Bob cannot | rdf | AWC | HEAD | false | 403 | | Bob cannot | container | AWC | HEAD | false | 403 | | Public cannot | plain | AWC | GET | true | 401 | + | Public cannot | fictive | AWC | GET | true | 401 | | Public cannot | rdf | AWC | GET | true | 401 | | Public cannot | container | AWC | GET | true | 401 | | Public cannot | plain | AWC | HEAD | true | 401 | + | Public cannot | fictive | AWC | HEAD | true | 401 | | Public cannot | rdf | AWC | HEAD | true | 401 | | Public cannot | container | AWC | HEAD | true | 401 | @@ -64,12 +73,16 @@ Feature: Only Bob can read (and only that) a resource when granted inherited rea Examples: | agent | type | mode | method | public! | status | | Bob | rdf | R | PUT | false | 403 | + | Bob | fictive | R | PUT | false | 403 | | Bob | container | R | PUT | false | 403 | | Bob | rdf | R | POST | false | 403 | + | Bob | fictive | R | POST | false | 404 | | Bob | container | R | POST | false | 403 | | Public | rdf | R | PUT | true | 401 | + | Public | fictive | R | PUT | true | 401 | | Public | container | R | PUT | true | 401 | | Public | rdf | R | POST | true | 401 | + | Public | fictive | R | POST | true | 401 | | Public | container | R | POST | true | 401 | Scenario Outline: cannot to a resource to which Bob has inherited access @@ -82,8 +95,10 @@ Feature: Only Bob can read (and only that) a resource when granted inherited rea Examples: | agent | type | mode | method | public! | status | | Bob | rdf | R | PATCH | false | 403 | + | Bob | fictive | R | PATCH | false | 403 | | Bob | container | R | PATCH | false | 403 | | Public | rdf | R | PATCH | true | 401 | + | Public | fictive | R | PATCH | true | 401 | | Public | container | R | PATCH | true | 401 | Scenario Outline: cannot to a resource to which Bob has inherited access @@ -98,9 +113,15 @@ Feature: Only Bob can read (and only that) a resource when granted inherited rea | Bob | plain | R | PUT | false | [403] | | Bob | plain | R | POST | false | [403] | | Bob | plain | R | PATCH | false | [403, 405, 415] | + | Bob | fictive | R | PUT | false | [403] | + | Bob | fictive | R | POST | false | [404] | + | Bob | fictive | R | PATCH | false | [403, 405, 415] | | Public | plain | R | PUT | true | [401] | | Public | plain | R | POST | true | [401] | | Public | plain | R | PATCH | true | [401, 405, 415] | + | Public | fictive | R | PUT | true | [401] | + | Public | fictive | R | POST | true | [401] | + | Public | fictive | R | PATCH | true | [401, 405, 415] | Scenario Outline: cannot a resource to which Bob has inherited access Given url tests[type].url @@ -110,8 +131,10 @@ Feature: Only Bob can read (and only that) a resource when granted inherited rea Examples: | agent | type | mode | method | public! | status | | Bob | plain | R | DELETE | false | 403 | + | Bob | fictive | R | DELETE | false | 404 | | Bob | rdf | R | DELETE | false | 403 | | Bob | container | R | DELETE | false | 403 | | Public | plain | R | DELETE | true | 401 | + | Public | fictive | R | DELETE | true | 401 | | Public | rdf | R | DELETE | true | 401 | | Public | container | R | DELETE | true | 401 | diff --git a/web-access-control/protected-operation/read-inherited-access-public.feature b/web-access-control/protected-operation/read-inherited-access-public.feature index 1ca5f0d..b4d28bc 100644 --- a/web-access-control/protected-operation/read-inherited-access-public.feature +++ b/web-access-control/protected-operation/read-inherited-access-public.feature @@ -12,9 +12,10 @@ Feature: Public agents can read (and only that) a resource when granted inherite .setPublicAccess(testContainer.url, ['read', 'write', 'append', 'control']) .setInheritablePublicAccess(testContainer.url, modes).build() const plainResource = testContainer.createResource('.txt', 'Hello', 'text/plain') + const fictiveResource = testContainer.reserveResource('.txt') const rdfResource = testContainer.createResource('.ttl', karate.readAsString('../fixtures/example.ttl'), 'text/turtle') const container = testContainer.createContainer() - return { plain: plainResource, rdf: rdfResource, container: container } + return { plain: plainResource, fictive: fictiveResource, rdf: rdfResource, container: container } } """ # Create 3 test resources with read access for public agents @@ -30,21 +31,27 @@ Feature: Public agents can read (and only that) a resource when granted inherite Examples: | agent | type | mode | method | public! | status | | Bob can | plain | R | GET | false | 200 | + | Bob can | fictive | R | GET | false | 404 | | Bob can | rdf | R | GET | false | 200 | | Bob can | container | R | GET | false | 200 | | Bob can | plain | R | HEAD | false | 200 | + | Bob can | fictive | R | HEAD | false | 404 | | Bob can | rdf | R | HEAD | false | 200 | | Bob can | container | R | HEAD | false | 200 | | Bob cannot | plain | AWC | GET | false | 403 | + | Bob cannot | fictive | AWC | GET | false | 403 | | Bob cannot | rdf | AWC | GET | false | 403 | | Bob cannot | container | AWC | GET | false | 403 | | Bob cannot | plain | AWC | HEAD | false | 403 | + | Bob cannot | fictive | AWC | HEAD | false | 403 | | Bob cannot | rdf | AWC | HEAD | false | 403 | | Bob cannot | container | AWC | HEAD | false | 403 | | Public cannot | plain | AWC | GET | true | 401 | + | Public cannot | fictive | AWC | GET | true | 401 | | Public cannot | rdf | AWC | GET | true | 401 | | Public cannot | container | AWC | GET | true | 401 | | Public cannot | plain | AWC | HEAD | true | 401 | + | Public cannot | fictive | AWC | HEAD | true | 401 | | Public cannot | rdf | AWC | HEAD | true | 401 | | Public cannot | container | AWC | HEAD | true | 401 | @@ -52,9 +59,11 @@ Feature: Public agents can read (and only that) a resource when granted inherite Examples: | agent | type | mode | method | public! | status | | Public can | plain | R | GET | true | 200 | + | Public can | fictive | R | GET | true | 404 | | Public can | rdf | R | GET | true | 200 | | Public can | container | R | GET | true | 200 | | Public can | plain | R | HEAD | true | 200 | + | Public can | fictive | R | HEAD | true | 404 | | Public can | rdf | R | HEAD | true | 200 | | Public can | container | R | HEAD | true | 200 | @@ -68,12 +77,16 @@ Feature: Public agents can read (and only that) a resource when granted inherite Examples: | agent | type | mode | method | public! | status | | Bob | rdf | R | PUT | false | 403 | + | Bob | fictive | R | PUT | false | 403 | | Bob | container | R | PUT | false | 403 | | Bob | rdf | R | POST | false | 403 | + | Bob | fictive | R | POST | false | 404 | | Bob | container | R | POST | false | 403 | | Public | rdf | R | PUT | true | 401 | + | Public | fictive | R | PUT | true | 401 | | Public | container | R | PUT | true | 401 | | Public | rdf | R | POST | true | 401 | + | Public | fictive | R | POST | true | 404 | | Public | container | R | POST | true | 401 | Scenario Outline: cannot to a resource to which a public agent has inherited access @@ -86,8 +99,10 @@ Feature: Public agents can read (and only that) a resource when granted inherite Examples: | agent | type | mode | method | public! | status | | Bob | rdf | R | PATCH | false | 403 | + | Bob | fictive | R | PATCH | false | 403 | | Bob | container | R | PATCH | false | 403 | | Public | rdf | R | PATCH | true | 401 | + | Public | fictive | R | PATCH | true | 401 | | Public | container | R | PATCH | true | 401 | Scenario Outline: cannot to a resource to which a public agent has inherited access @@ -102,9 +117,15 @@ Feature: Public agents can read (and only that) a resource when granted inherite | Bob | plain | R | PUT | false | [403] | | Bob | plain | R | POST | false | [403] | | Bob | plain | R | PATCH | false | [403, 405, 415] | + | Bob | fictive | R | PUT | false | [403] | + | Bob | fictive | R | POST | false | [404] | + | Bob | fictive | R | PATCH | false | [403, 405, 415] | | Public | plain | R | PUT | true | [401] | | Public | plain | R | POST | true | [401] | | Public | plain | R | PATCH | true | [401, 405, 415] | + | Public | fictive | R | PUT | true | [401] | + | Public | fictive | R | POST | true | [404] | + | Public | fictive | R | PATCH | true | [401, 405, 415] | Scenario Outline: cannot a resource to which a public agent has inherited access Given url tests[type].url @@ -114,8 +135,10 @@ Feature: Public agents can read (and only that) a resource when granted inherite Examples: | agent | type | mode | method | public! | status | | Bob | plain | R | DELETE | false | 403 | + | Bob | fictive | R | DELETE | false | 404 | | Bob | rdf | R | DELETE | false | 403 | | Bob | container | R | DELETE | false | 403 | | Public | plain | R | DELETE | true | 401 | + | Public | fictive | R | DELETE | true | 404 | | Public | rdf | R | DELETE | true | 401 | | Public | container | R | DELETE | true | 401 | From 4fed180fd6e69cca27d37c8571ee4a606affee68 Mon Sep 17 00:00:00 2001 From: surilindur Date: Fri, 12 Aug 2022 16:53:35 +0300 Subject: [PATCH 2/8] added CSS-inspired test tables --- .../access-permissions-agent.feature | 165 +++++++++++++++++ .../access-permissions-bob.feature | 165 +++++++++++++++++ .../access-permissions-public.feature | 171 ++++++++++++++++++ .../web-access-control-test-manifest.ttl | 21 +++ 4 files changed, 522 insertions(+) create mode 100644 web-access-control/protected-operation/access-permissions-agent.feature create mode 100644 web-access-control/protected-operation/access-permissions-bob.feature create mode 100644 web-access-control/protected-operation/access-permissions-public.feature diff --git a/web-access-control/protected-operation/access-permissions-agent.feature b/web-access-control/protected-operation/access-permissions-agent.feature new file mode 100644 index 0000000..a72fc5c --- /dev/null +++ b/web-access-control/protected-operation/access-permissions-agent.feature @@ -0,0 +1,165 @@ +Feature: Access permissions and return codes for authenticated users reflect container and resource permissions + Background: Prepare functions for generating resources for test cases + * def authHeaders = (method, client, url) => client == 'public' ? {} : clients[client].getAuthHeaders(method, url) + * def prepareResources = + """ + function (containerModes, resourceModes, resourceType, client) { + + // containerModes, resourceModes = 'RWAC' or any combination thereof, or nothing for no permissions + + const resolvePermissions = function(modes) { + return modes + ? Object.entries({ R: 'read', W: 'write', A: 'append', C: 'control' }).filter(([mode, permission]) => modes.includes(mode)).map(([mode, permission]) => permission) + : [] + } + + const createResourceByType = function(containerToCreateIn, typeToCreate) { + switch (typeToCreate) { + case 'plain': + return containerToCreateIn.createResource('.txt', 'Hello', 'text/plain') + case 'fictive': + return containerToCreateIn.reserveResource('.txt') + case 'rdf': + return containerToCreateIn.createResource('.ttl', karate.readAsString('../fixtures/example.ttl'), 'text/turtle') + case 'container': + return containerToCreateIn.createContainer() + } + } + + const getAccessDatasetByPermissions = function(resource, client, permissions, inheritable) { + return inheritable + ? resource.accessDatasetBuilder.setInheritableAuthenticatedAccess(resource.url, permissions) + : resource.accessDatasetBuilder.setAuthenticatedAccess(resource.url, permissions) + } + + const testContainer = rootTestContainer.createContainer() + const testResource = createResourceByType(testContainer, resourceType) + + const containerPermissions = resolvePermissions(containerModes) + const resourcePermissions = resourceModes == 'inherited' ? undefined : resolvePermissions(resourceModes) + + // console.log(`Container: ${containerPermissions}, Resource: ${resourcePermissions}`) + + if (containerPermissions) { + testContainer.accessDataset = getAccessDatasetByPermissions(testContainer, client, containerPermissions, resourcePermissions ? false : true).build() + } + + if (resourcePermissions && resourceType != 'fictive') { + testResource.accessDataset = getAccessDatasetByPermissions(testResource, client, resourcePermissions, false).build() + } + + return { container: testContainer, resource: testResource } + } + """ + + Scenario Outline: by on resource produces with permissions on container and permissions on resource + Given def testResources = prepareResources(container, resource, type, client) + And url testResources.resource.url + And headers authHeaders(method, client, testResources.resource.url) + When method + Then status + Examples: + | method | client | container | resource | type | status | + | OPTIONS | bob | no | inherited | rdf | 204 | + | OPTIONS | bob | no | inherited | plain | 204 | + | OPTIONS | bob | no | inherited | fictive | 204 | + | OPTIONS | bob | no | inherited | container | 204 | + | OPTIONS | bob | no | R | rdf | 204 | + | OPTIONS | bob | no | R | plain | 204 | + | OPTIONS | bob | no | R | fictive | 204 | + | OPTIONS | bob | no | R | container | 204 | + | OPTIONS | bob | R | inherited | rdf | 204 | + | OPTIONS | bob | R | inherited | plain | 204 | + | OPTIONS | bob | R | inherited | fictive | 204 | + | OPTIONS | bob | R | inherited | container | 204 | + | HEAD | bob | no | inherited | rdf | 403 | + | HEAD | bob | no | inherited | plain | 403 | + | HEAD | bob | no | inherited | fictive | 403 | + | HEAD | bob | no | inherited | container | 403 | + | HEAD | bob | no | R | rdf | 200 | + | HEAD | bob | no | R | plain | 200 | + #| HEAD | bob | no | R | fictive | 404 | + | HEAD | bob | no | R | container | 200 | + | HEAD | bob | R | inherited | rdf | 200 | + | HEAD | bob | R | inherited | plain | 200 | + | HEAD | bob | R | inherited | fictive | 404 | + | HEAD | bob | R | inherited | container | 200 | + | GET | bob | no | inherited | rdf | 403 | + | GET | bob | no | inherited | plain | 403 | + | GET | bob | no | inherited | fictive | 403 | + | GET | bob | no | inherited | container | 403 | + | GET | bob | no | R | rdf | 200 | + | GET | bob | no | R | plain | 200 | + #| GET | bob | no | R | fictive | 404 | + | GET | bob | no | R | container | 200 | + | GET | bob | R | inherited | rdf | 200 | + | GET | bob | R | inherited | plain | 200 | + | GET | bob | R | inherited | fictive | 404 | + | GET | bob | R | inherited | container | 200 | + | GET | bob | R | W | rdf | 403 | + | GET | bob | R | W | plain | 403 | + | GET | bob | R | W | fictive | 403 | + | GET | bob | R | W | container | 403 | + + Scenario Outline: by on container produces with permissions on container and permissions on resource + Given def testResources = prepareResources(container, resource, type, client) + And url testResources.container.url + And headers authHeaders(method, client, testResources.container.url) + And header Content-Type = 'text/turtle' + And request '@prefix rdfs: . <> rdfs:comment "Bob added this.".' + When method + Then status + Examples: + | method | client | container | resource | type | status | + | POST | bob | no | inherited | fictive | 403 | + | POST | bob | no | R | fictive | 403 | + | POST | bob | A | inherited | fictive | 403 | + | POST | bob | A | R | fictive | 201 | + | POST | bob | RA | inherited | fictive | 403 | + | POST | bob | RA | R | fictive | 201 | + | PUT | bob | no | inherited | fictive | 403 | + | PUT | bob | R | inherited | fictive | 403 | + | PUT | bob | W | inherited | fictive | 403 | + + Scenario Outline: by on resource produces with permissions on container and permissions on resource + Given def testResources = prepareResources(container, resource, type, client) + And url testResources.resource.url + And headers authHeaders(method, client, testResources.resource.url) + And header Content-Type = 'text/plain' + And request "Bob's text" + When method + Then status + Examples: + | method | client | container | resource | type | status | + | PUT | bob | no | inherited | plain | 403 | + | PUT | bob | no | inherited | fictive | 403 | + | PUT | bob | no | R | plain | 403 | + | PUT | bob | no | R | fictive | 403 | + | PUT | bob | no | A | plain | 403 | + | PUT | bob | no | A | fictive | 403 | + | PUT | bob | no | W | plain | 205 | + | PUT | bob | no | W | fictive | 403 | + | PUT | bob | R | inherited | plain | 403 | + | PUT | bob | R | inherited | fictive | 403 | + | PUT | bob | A | inherited | plain | 403 | + | PUT | bob | A | inherited | fictive | 403 | + | PUT | bob | W | inherited | plain | 205 | + #| PUT | bob | W | inherited | fictive | 201 | + | PUT | bob | A | W | plain | 205 | + #| PUT | bob | A | W | fictive | 201 | + | POST | bob | no | inherited | plain | 403 | + | POST | bob | no | inherited | fictive | 403 | + | POST | bob | no | R | plain | 403 | + | POST | bob | no | R | fictive | 403 | + | POST | bob | no | A | plain | 405 | + | POST | bob | no | A | fictive | 403 | + | POST | bob | no | W | plain | 405 | + | POST | bob | no | W | fictive | 403 | + | POST | bob | R | inherited | plain | 403 | + | POST | bob | R | inherited | fictive | 404 | + | POST | bob | A | inherited | plain | 405 | + | POST | bob | A | inherited | fictive | 404 | + | POST | bob | W | inherited | plain | 405 | + #| POST | bob | W | inherited | fictive | 201 | + | POST | bob | A | W | plain | 405 | + #| POST | bob | A | W | fictive | 201 | diff --git a/web-access-control/protected-operation/access-permissions-bob.feature b/web-access-control/protected-operation/access-permissions-bob.feature new file mode 100644 index 0000000..9f8664b --- /dev/null +++ b/web-access-control/protected-operation/access-permissions-bob.feature @@ -0,0 +1,165 @@ +Feature: Access permissions and return codes for Bob reflect container and resource permissions + Background: Prepare functions for generating resources for test cases + * def authHeaders = (method, client, url) => client == 'public' ? {} : clients[client].getAuthHeaders(method, url) + * def prepareResources = + """ + function (containerModes, resourceModes, resourceType, client) { + + // containerModes, resourceModes = 'RWAC' or any combination thereof, or nothing for no permissions + + const resolvePermissions = function(modes) { + return modes + ? Object.entries({ R: 'read', W: 'write', A: 'append', C: 'control' }).filter(([mode, permission]) => modes.includes(mode)).map(([mode, permission]) => permission) + : [] + } + + const createResourceByType = function(containerToCreateIn, typeToCreate) { + switch (typeToCreate) { + case 'plain': + return containerToCreateIn.createResource('.txt', 'Hello', 'text/plain') + case 'fictive': + return containerToCreateIn.reserveResource('.txt') + case 'rdf': + return containerToCreateIn.createResource('.ttl', karate.readAsString('../fixtures/example.ttl'), 'text/turtle') + case 'container': + return containerToCreateIn.createContainer() + } + } + + const getAccessDatasetByPermissions = function(resource, client, permissions, inheritable) { + return inheritable + ? resource.accessDatasetBuilder.setInheritableAgentAccess(resource.url, webIds[client], permissions) + : resource.accessDatasetBuilder.setAgentAccess(resource.url, webIds[client], permissions) + } + + const testContainer = rootTestContainer.createContainer() + const testResource = createResourceByType(testContainer, resourceType) + + const containerPermissions = resolvePermissions(containerModes) + const resourcePermissions = resourceModes == 'inherited' ? undefined : resolvePermissions(resourceModes) + + // console.log(`Container: ${containerPermissions}, Resource: ${resourcePermissions}`) + + if (containerPermissions) { + testContainer.accessDataset = getAccessDatasetByPermissions(testContainer, client, containerPermissions, resourcePermissions ? false : true).build() + } + + if (resourcePermissions && resourceType != 'fictive') { + testResource.accessDataset = getAccessDatasetByPermissions(testResource, client, resourcePermissions, false).build() + } + + return { container: testContainer, resource: testResource } + } + """ + + Scenario Outline: by on resource produces with permissions on container and permissions on resource + Given def testResources = prepareResources(container, resource, type, client) + And url testResources.resource.url + And headers authHeaders(method, client, testResources.resource.url) + When method + Then status + Examples: + | method | client | container | resource | type | status | + | OPTIONS | bob | no | inherited | rdf | 204 | + | OPTIONS | bob | no | inherited | plain | 204 | + | OPTIONS | bob | no | inherited | fictive | 204 | + | OPTIONS | bob | no | inherited | container | 204 | + | OPTIONS | bob | no | R | rdf | 204 | + | OPTIONS | bob | no | R | plain | 204 | + | OPTIONS | bob | no | R | fictive | 204 | + | OPTIONS | bob | no | R | container | 204 | + | OPTIONS | bob | R | inherited | rdf | 204 | + | OPTIONS | bob | R | inherited | plain | 204 | + | OPTIONS | bob | R | inherited | fictive | 204 | + | OPTIONS | bob | R | inherited | container | 204 | + | HEAD | bob | no | inherited | rdf | 403 | + | HEAD | bob | no | inherited | plain | 403 | + | HEAD | bob | no | inherited | fictive | 403 | + | HEAD | bob | no | inherited | container | 403 | + | HEAD | bob | no | R | rdf | 200 | + | HEAD | bob | no | R | plain | 200 | + #| HEAD | bob | no | R | fictive | 404 | + | HEAD | bob | no | R | container | 200 | + | HEAD | bob | R | inherited | rdf | 200 | + | HEAD | bob | R | inherited | plain | 200 | + | HEAD | bob | R | inherited | fictive | 404 | + | HEAD | bob | R | inherited | container | 200 | + | GET | bob | no | inherited | rdf | 403 | + | GET | bob | no | inherited | plain | 403 | + | GET | bob | no | inherited | fictive | 403 | + | GET | bob | no | inherited | container | 403 | + | GET | bob | no | R | rdf | 200 | + | GET | bob | no | R | plain | 200 | + #| GET | bob | no | R | fictive | 404 | + | GET | bob | no | R | container | 200 | + | GET | bob | R | inherited | rdf | 200 | + | GET | bob | R | inherited | plain | 200 | + | GET | bob | R | inherited | fictive | 404 | + | GET | bob | R | inherited | container | 200 | + | GET | bob | R | W | rdf | 403 | + | GET | bob | R | W | plain | 403 | + | GET | bob | R | W | fictive | 403 | + | GET | bob | R | W | container | 403 | + + Scenario Outline: by on container produces with permissions on container and permissions on resource + Given def testResources = prepareResources(container, resource, type, client) + And url testResources.container.url + And headers authHeaders(method, client, testResources.container.url) + And header Content-Type = 'text/turtle' + And request '@prefix rdfs: . <> rdfs:comment "Bob added this.".' + When method + Then status + Examples: + | method | client | container | resource | type | status | + | POST | bob | no | inherited | fictive | 403 | + | POST | bob | no | R | fictive | 403 | + | POST | bob | A | inherited | fictive | 403 | + | POST | bob | A | R | fictive | 201 | + | POST | bob | RA | inherited | fictive | 403 | + | POST | bob | RA | R | fictive | 201 | + | PUT | bob | no | inherited | fictive | 403 | + | PUT | bob | R | inherited | fictive | 403 | + | PUT | bob | W | inherited | fictive | 403 | + + Scenario Outline: by on resource produces with permissions on container and permissions on resource + Given def testResources = prepareResources(container, resource, type, client) + And url testResources.resource.url + And headers authHeaders(method, client, testResources.resource.url) + And header Content-Type = 'text/plain' + And request "Bob's text" + When method + Then status + Examples: + | method | client | container | resource | type | status | + | PUT | bob | no | inherited | plain | 403 | + | PUT | bob | no | inherited | fictive | 403 | + | PUT | bob | no | R | plain | 403 | + | PUT | bob | no | R | fictive | 403 | + | PUT | bob | no | A | plain | 403 | + | PUT | bob | no | A | fictive | 403 | + | PUT | bob | no | W | plain | 205 | + | PUT | bob | no | W | fictive | 403 | + | PUT | bob | R | inherited | plain | 403 | + | PUT | bob | R | inherited | fictive | 403 | + | PUT | bob | A | inherited | plain | 403 | + | PUT | bob | A | inherited | fictive | 403 | + | PUT | bob | W | inherited | plain | 205 | + #| PUT | bob | W | inherited | fictive | 201 | + | PUT | bob | A | W | plain | 205 | + #| PUT | bob | A | W | fictive | 201 | + | POST | bob | no | inherited | plain | 403 | + | POST | bob | no | inherited | fictive | 403 | + | POST | bob | no | R | plain | 403 | + | POST | bob | no | R | fictive | 403 | + | POST | bob | no | A | plain | 405 | + | POST | bob | no | A | fictive | 403 | + | POST | bob | no | W | plain | 405 | + | POST | bob | no | W | fictive | 403 | + | POST | bob | R | inherited | plain | 403 | + | POST | bob | R | inherited | fictive | 404 | + | POST | bob | A | inherited | plain | 405 | + | POST | bob | A | inherited | fictive | 404 | + | POST | bob | W | inherited | plain | 405 | + #| POST | bob | W | inherited | fictive | 201 | + | POST | bob | A | W | plain | 405 | + #| POST | bob | A | W | fictive | 201 | diff --git a/web-access-control/protected-operation/access-permissions-public.feature b/web-access-control/protected-operation/access-permissions-public.feature new file mode 100644 index 0000000..7ee55f3 --- /dev/null +++ b/web-access-control/protected-operation/access-permissions-public.feature @@ -0,0 +1,171 @@ +Feature: Access permissions and return codes for public reflect container and resource permissions + Background: Prepare functions for generating resources for test cases + * def authHeaders = (method, client, url) => client == 'public' ? {} : clients[client].getAuthHeaders(method, url) + * def prepareResources = + """ + function (containerModes, resourceModes, resourceType, client) { + + // containerModes, resourceModes = 'RWAC' or any combination thereof, or nothing for no permissions + + const resolvePermissions = function(modes) { + return modes + ? Object.entries({ R: 'read', W: 'write', A: 'append', C: 'control' }).filter(([mode, permission]) => modes.includes(mode)).map(([mode, permission]) => permission) + : [] + } + + const createResourceByType = function(containerToCreateIn, typeToCreate) { + switch (typeToCreate) { + case 'plain': + return containerToCreateIn.createResource('.txt', 'Hello', 'text/plain') + case 'fictive': + return containerToCreateIn.reserveResource('.txt') + case 'rdf': + return containerToCreateIn.createResource('.ttl', karate.readAsString('../fixtures/example.ttl'), 'text/turtle') + case 'container': + return containerToCreateIn.createContainer() + } + } + + const getAccessDatasetByPermissions = function(resource, client, permissions, inheritable) { + return inheritable + ? resource.accessDatasetBuilder.setInheritablePublicAccess(resource.url, permissions) + : resource.accessDatasetBuilder.setPublicAccess(resource.url, permissions) + //return inheritable + // ? resource.accessDatasetBuilder.setInheritableAuthenticatedAccess(resource.url, permissions) + // : resource.accessDatasetBuilder.setAuthenticatedAccess(resource.url, permissions) + //return inheritable + // ? resource.accessDatasetBuilder.setInheritableAgentAccess(resource.url, webIds[client], permissions) + // : resource.accessDatasetBuilder.setAgentAccess(resource.url, webIds[client], permissions) + } + + const testContainer = rootTestContainer.createContainer() + const testResource = createResourceByType(testContainer, resourceType) + + const containerPermissions = resolvePermissions(containerModes) + const resourcePermissions = resourceModes == 'inherited' ? undefined : resolvePermissions(resourceModes) + + // console.log(`Container: ${containerPermissions}, Resource: ${resourcePermissions}`) + + if (containerPermissions) { + testContainer.accessDataset = getAccessDatasetByPermissions(testContainer, client, containerPermissions, resourcePermissions ? false : true).build() + } + + if (resourcePermissions && resourceType != 'fictive') { + testResource.accessDataset = getAccessDatasetByPermissions(testResource, client, resourcePermissions, false).build() + } + + return { container: testContainer, resource: testResource } + } + """ + + Scenario Outline: by on resource produces with permissions on container and permissions on resource + Given def testResources = prepareResources(container, resource, type, client) + And url testResources.resource.url + And headers authHeaders(method, client, testResources.resource.url) + When method + Then status + Examples: + | method | client | container | resource | type | status | + | OPTIONS | public | no | inherited | rdf | 204 | + | OPTIONS | public | no | inherited | plain | 204 | + | OPTIONS | public | no | inherited | fictive | 204 | + | OPTIONS | public | no | inherited | container | 204 | + | OPTIONS | public | no | R | rdf | 204 | + | OPTIONS | public | no | R | plain | 204 | + | OPTIONS | public | no | R | fictive | 204 | + | OPTIONS | public | no | R | container | 204 | + | OPTIONS | public | R | inherited | rdf | 204 | + | OPTIONS | public | R | inherited | plain | 204 | + | OPTIONS | public | R | inherited | fictive | 204 | + | OPTIONS | public | R | inherited | container | 204 | + | HEAD | public | no | inherited | rdf | 401 | + | HEAD | public | no | inherited | plain | 401 | + | HEAD | public | no | inherited | fictive | 401 | + | HEAD | public | no | inherited | container | 401 | + | HEAD | public | no | R | rdf | 200 | + | HEAD | public | no | R | plain | 200 | + #| HEAD | public | no | R | fictive | 404 | + | HEAD | public | no | R | container | 200 | + | HEAD | public | R | inherited | rdf | 200 | + | HEAD | public | R | inherited | plain | 200 | + | HEAD | public | R | inherited | fictive | 404 | + | HEAD | public | R | inherited | container | 200 | + | GET | public | no | inherited | rdf | 401 | + | GET | public | no | inherited | plain | 401 | + | GET | public | no | inherited | fictive | 401 | + | GET | public | no | inherited | container | 401 | + | GET | public | no | R | rdf | 200 | + | GET | public | no | R | plain | 200 | + #| GET | public | no | R | fictive | 404 | + | GET | public | no | R | container | 200 | + | GET | public | R | inherited | rdf | 200 | + | GET | public | R | inherited | plain | 200 | + | GET | public | R | inherited | fictive | 404 | + | GET | public | R | inherited | container | 200 | + | GET | public | R | W | rdf | 401 | + | GET | public | R | W | plain | 401 | + | GET | public | R | W | fictive | 401 | + | GET | public | R | W | container | 401 | + + Scenario Outline: by on container produces with permissions on container and permissions on resource + Given def testResources = prepareResources(container, resource, type, client) + And url testResources.container.url + And headers authHeaders(method, client, testResources.container.url) + And header Content-Type = 'text/turtle' + And request '@prefix rdfs: . <> rdfs:comment "Public added this.".' + When method + Then status + Examples: + | method | client | container | resource | type | status | + | POST | public | no | inherited | fictive | 401 | + | POST | public | no | R | fictive | 401 | + | POST | public | A | inherited | fictive | 401 | + | POST | public | A | R | fictive | 201 | + | POST | public | RA | inherited | fictive | 401 | + | POST | public | RA | R | fictive | 201 | + | PUT | public | no | inherited | fictive | 401 | + | PUT | public | R | inherited | fictive | 401 | + | PUT | public | W | inherited | fictive | 401 | + + Scenario Outline: by on resource produces with permissions on container and permissions on resource + Given def testResources = prepareResources(container, resource, type, client) + And url testResources.resource.url + And headers authHeaders(method, client, testResources.resource.url) + And header Content-Type = 'text/plain' + And request "Public's text" + When method + Then status + Examples: + | method | client | container | resource | type | status | + | PUT | public | no | inherited | plain | 401 | + | PUT | public | no | inherited | fictive | 401 | + | PUT | public | no | R | plain | 401 | + | PUT | public | no | R | fictive | 401 | + | PUT | public | no | A | plain | 401 | + | PUT | public | no | A | fictive | 401 | + | PUT | public | no | W | plain | 205 | + | PUT | public | no | W | fictive | 401 | + | PUT | public | R | inherited | plain | 401 | + | PUT | public | R | inherited | fictive | 401 | + | PUT | public | A | inherited | plain | 401 | + | PUT | public | A | inherited | fictive | 401 | + | PUT | public | W | inherited | plain | 205 | + #| PUT | public | W | inherited | fictive | 201 | + | PUT | public | A | W | plain | 205 | + #| PUT | public | A | W | fictive | 201 | + | POST | public | no | inherited | plain | 401 | + | POST | public | no | inherited | fictive | 401 | + | POST | public | no | R | plain | 401 | + | POST | public | no | R | fictive | 401 | + | POST | public | no | A | plain | 405 | + | POST | public | no | A | fictive | 401 | + | POST | public | no | W | plain | 405 | + | POST | public | no | W | fictive | 401 | + | POST | public | R | inherited | plain | 401 | + | POST | public | R | inherited | fictive | 404 | + | POST | public | A | inherited | plain | 405 | + | POST | public | A | inherited | fictive | 404 | + | POST | public | W | inherited | plain | 405 | + #| POST | public | W | inherited | fictive | 201 | + | POST | public | A | W | plain | 405 | + #| POST | public | A | W | fictive | 201 | diff --git a/web-access-control/web-access-control-test-manifest.ttl b/web-access-control/web-access-control-test-manifest.ttl index 99d12c1..d2a2e13 100644 --- a/web-access-control/web-access-control-test-manifest.ttl +++ b/web-access-control/web-access-control-test-manifest.ttl @@ -90,6 +90,27 @@ manifest:server-wac-allow-public-access-indirect spec:testScript . +manifest:access-permissions-agent + a td:TestCase ; + spec:requirementReference wac:server-read-operation ; + td:reviewStatus td:unreviewed ; + spec:testScript + . + +manifest:access-permissions-bob + a td:TestCase ; + spec:requirementReference wac:server-read-operation ; + td:reviewStatus td:unreviewed ; + spec:testScript + . + +manifest:access-permissions-public + a td:TestCase ; + spec:requirementReference wac:server-read-operation ; + td:reviewStatus td:unreviewed ; + spec:testScript + . + manifest:read-access-bob a td:TestCase ; spec:requirementReference wac:server-read-operation ; From aa5ee57156cb4f70f626fb3cafe002d7aa7a1090 Mon Sep 17 00:00:00 2001 From: surilindur Date: Tue, 16 Aug 2022 11:23:46 +0300 Subject: [PATCH 3/8] moved test changes to existing files, merged inherited and not inherited permission tests --- .../access-permissions-agent.feature | 165 --------- .../access-permissions-bob.feature | 165 --------- .../access-permissions-public.feature | 171 --------- .../read-access-agent.feature | 334 +++++++++++------ .../read-access-bob.feature | 335 +++++++++++------ .../read-access-public.feature | 336 ++++++++++++------ .../read-inherited-access-agent.feature | 140 -------- .../read-inherited-access-bob.feature | 140 -------- .../read-inherited-access-public.feature | 144 -------- .../web-access-control-test-manifest.ttl | 42 --- 10 files changed, 680 insertions(+), 1292 deletions(-) delete mode 100644 web-access-control/protected-operation/access-permissions-agent.feature delete mode 100644 web-access-control/protected-operation/access-permissions-bob.feature delete mode 100644 web-access-control/protected-operation/access-permissions-public.feature delete mode 100644 web-access-control/protected-operation/read-inherited-access-agent.feature delete mode 100644 web-access-control/protected-operation/read-inherited-access-bob.feature delete mode 100644 web-access-control/protected-operation/read-inherited-access-public.feature diff --git a/web-access-control/protected-operation/access-permissions-agent.feature b/web-access-control/protected-operation/access-permissions-agent.feature deleted file mode 100644 index a72fc5c..0000000 --- a/web-access-control/protected-operation/access-permissions-agent.feature +++ /dev/null @@ -1,165 +0,0 @@ -Feature: Access permissions and return codes for authenticated users reflect container and resource permissions - Background: Prepare functions for generating resources for test cases - * def authHeaders = (method, client, url) => client == 'public' ? {} : clients[client].getAuthHeaders(method, url) - * def prepareResources = - """ - function (containerModes, resourceModes, resourceType, client) { - - // containerModes, resourceModes = 'RWAC' or any combination thereof, or nothing for no permissions - - const resolvePermissions = function(modes) { - return modes - ? Object.entries({ R: 'read', W: 'write', A: 'append', C: 'control' }).filter(([mode, permission]) => modes.includes(mode)).map(([mode, permission]) => permission) - : [] - } - - const createResourceByType = function(containerToCreateIn, typeToCreate) { - switch (typeToCreate) { - case 'plain': - return containerToCreateIn.createResource('.txt', 'Hello', 'text/plain') - case 'fictive': - return containerToCreateIn.reserveResource('.txt') - case 'rdf': - return containerToCreateIn.createResource('.ttl', karate.readAsString('../fixtures/example.ttl'), 'text/turtle') - case 'container': - return containerToCreateIn.createContainer() - } - } - - const getAccessDatasetByPermissions = function(resource, client, permissions, inheritable) { - return inheritable - ? resource.accessDatasetBuilder.setInheritableAuthenticatedAccess(resource.url, permissions) - : resource.accessDatasetBuilder.setAuthenticatedAccess(resource.url, permissions) - } - - const testContainer = rootTestContainer.createContainer() - const testResource = createResourceByType(testContainer, resourceType) - - const containerPermissions = resolvePermissions(containerModes) - const resourcePermissions = resourceModes == 'inherited' ? undefined : resolvePermissions(resourceModes) - - // console.log(`Container: ${containerPermissions}, Resource: ${resourcePermissions}`) - - if (containerPermissions) { - testContainer.accessDataset = getAccessDatasetByPermissions(testContainer, client, containerPermissions, resourcePermissions ? false : true).build() - } - - if (resourcePermissions && resourceType != 'fictive') { - testResource.accessDataset = getAccessDatasetByPermissions(testResource, client, resourcePermissions, false).build() - } - - return { container: testContainer, resource: testResource } - } - """ - - Scenario Outline: by on resource produces with permissions on container and permissions on resource - Given def testResources = prepareResources(container, resource, type, client) - And url testResources.resource.url - And headers authHeaders(method, client, testResources.resource.url) - When method - Then status - Examples: - | method | client | container | resource | type | status | - | OPTIONS | bob | no | inherited | rdf | 204 | - | OPTIONS | bob | no | inherited | plain | 204 | - | OPTIONS | bob | no | inherited | fictive | 204 | - | OPTIONS | bob | no | inherited | container | 204 | - | OPTIONS | bob | no | R | rdf | 204 | - | OPTIONS | bob | no | R | plain | 204 | - | OPTIONS | bob | no | R | fictive | 204 | - | OPTIONS | bob | no | R | container | 204 | - | OPTIONS | bob | R | inherited | rdf | 204 | - | OPTIONS | bob | R | inherited | plain | 204 | - | OPTIONS | bob | R | inherited | fictive | 204 | - | OPTIONS | bob | R | inherited | container | 204 | - | HEAD | bob | no | inherited | rdf | 403 | - | HEAD | bob | no | inherited | plain | 403 | - | HEAD | bob | no | inherited | fictive | 403 | - | HEAD | bob | no | inherited | container | 403 | - | HEAD | bob | no | R | rdf | 200 | - | HEAD | bob | no | R | plain | 200 | - #| HEAD | bob | no | R | fictive | 404 | - | HEAD | bob | no | R | container | 200 | - | HEAD | bob | R | inherited | rdf | 200 | - | HEAD | bob | R | inherited | plain | 200 | - | HEAD | bob | R | inherited | fictive | 404 | - | HEAD | bob | R | inherited | container | 200 | - | GET | bob | no | inherited | rdf | 403 | - | GET | bob | no | inherited | plain | 403 | - | GET | bob | no | inherited | fictive | 403 | - | GET | bob | no | inherited | container | 403 | - | GET | bob | no | R | rdf | 200 | - | GET | bob | no | R | plain | 200 | - #| GET | bob | no | R | fictive | 404 | - | GET | bob | no | R | container | 200 | - | GET | bob | R | inherited | rdf | 200 | - | GET | bob | R | inherited | plain | 200 | - | GET | bob | R | inherited | fictive | 404 | - | GET | bob | R | inherited | container | 200 | - | GET | bob | R | W | rdf | 403 | - | GET | bob | R | W | plain | 403 | - | GET | bob | R | W | fictive | 403 | - | GET | bob | R | W | container | 403 | - - Scenario Outline: by on container produces with permissions on container and permissions on resource - Given def testResources = prepareResources(container, resource, type, client) - And url testResources.container.url - And headers authHeaders(method, client, testResources.container.url) - And header Content-Type = 'text/turtle' - And request '@prefix rdfs: . <> rdfs:comment "Bob added this.".' - When method - Then status - Examples: - | method | client | container | resource | type | status | - | POST | bob | no | inherited | fictive | 403 | - | POST | bob | no | R | fictive | 403 | - | POST | bob | A | inherited | fictive | 403 | - | POST | bob | A | R | fictive | 201 | - | POST | bob | RA | inherited | fictive | 403 | - | POST | bob | RA | R | fictive | 201 | - | PUT | bob | no | inherited | fictive | 403 | - | PUT | bob | R | inherited | fictive | 403 | - | PUT | bob | W | inherited | fictive | 403 | - - Scenario Outline: by on resource produces with permissions on container and permissions on resource - Given def testResources = prepareResources(container, resource, type, client) - And url testResources.resource.url - And headers authHeaders(method, client, testResources.resource.url) - And header Content-Type = 'text/plain' - And request "Bob's text" - When method - Then status - Examples: - | method | client | container | resource | type | status | - | PUT | bob | no | inherited | plain | 403 | - | PUT | bob | no | inherited | fictive | 403 | - | PUT | bob | no | R | plain | 403 | - | PUT | bob | no | R | fictive | 403 | - | PUT | bob | no | A | plain | 403 | - | PUT | bob | no | A | fictive | 403 | - | PUT | bob | no | W | plain | 205 | - | PUT | bob | no | W | fictive | 403 | - | PUT | bob | R | inherited | plain | 403 | - | PUT | bob | R | inherited | fictive | 403 | - | PUT | bob | A | inherited | plain | 403 | - | PUT | bob | A | inherited | fictive | 403 | - | PUT | bob | W | inherited | plain | 205 | - #| PUT | bob | W | inherited | fictive | 201 | - | PUT | bob | A | W | plain | 205 | - #| PUT | bob | A | W | fictive | 201 | - | POST | bob | no | inherited | plain | 403 | - | POST | bob | no | inherited | fictive | 403 | - | POST | bob | no | R | plain | 403 | - | POST | bob | no | R | fictive | 403 | - | POST | bob | no | A | plain | 405 | - | POST | bob | no | A | fictive | 403 | - | POST | bob | no | W | plain | 405 | - | POST | bob | no | W | fictive | 403 | - | POST | bob | R | inherited | plain | 403 | - | POST | bob | R | inherited | fictive | 404 | - | POST | bob | A | inherited | plain | 405 | - | POST | bob | A | inherited | fictive | 404 | - | POST | bob | W | inherited | plain | 405 | - #| POST | bob | W | inherited | fictive | 201 | - | POST | bob | A | W | plain | 405 | - #| POST | bob | A | W | fictive | 201 | diff --git a/web-access-control/protected-operation/access-permissions-bob.feature b/web-access-control/protected-operation/access-permissions-bob.feature deleted file mode 100644 index 9f8664b..0000000 --- a/web-access-control/protected-operation/access-permissions-bob.feature +++ /dev/null @@ -1,165 +0,0 @@ -Feature: Access permissions and return codes for Bob reflect container and resource permissions - Background: Prepare functions for generating resources for test cases - * def authHeaders = (method, client, url) => client == 'public' ? {} : clients[client].getAuthHeaders(method, url) - * def prepareResources = - """ - function (containerModes, resourceModes, resourceType, client) { - - // containerModes, resourceModes = 'RWAC' or any combination thereof, or nothing for no permissions - - const resolvePermissions = function(modes) { - return modes - ? Object.entries({ R: 'read', W: 'write', A: 'append', C: 'control' }).filter(([mode, permission]) => modes.includes(mode)).map(([mode, permission]) => permission) - : [] - } - - const createResourceByType = function(containerToCreateIn, typeToCreate) { - switch (typeToCreate) { - case 'plain': - return containerToCreateIn.createResource('.txt', 'Hello', 'text/plain') - case 'fictive': - return containerToCreateIn.reserveResource('.txt') - case 'rdf': - return containerToCreateIn.createResource('.ttl', karate.readAsString('../fixtures/example.ttl'), 'text/turtle') - case 'container': - return containerToCreateIn.createContainer() - } - } - - const getAccessDatasetByPermissions = function(resource, client, permissions, inheritable) { - return inheritable - ? resource.accessDatasetBuilder.setInheritableAgentAccess(resource.url, webIds[client], permissions) - : resource.accessDatasetBuilder.setAgentAccess(resource.url, webIds[client], permissions) - } - - const testContainer = rootTestContainer.createContainer() - const testResource = createResourceByType(testContainer, resourceType) - - const containerPermissions = resolvePermissions(containerModes) - const resourcePermissions = resourceModes == 'inherited' ? undefined : resolvePermissions(resourceModes) - - // console.log(`Container: ${containerPermissions}, Resource: ${resourcePermissions}`) - - if (containerPermissions) { - testContainer.accessDataset = getAccessDatasetByPermissions(testContainer, client, containerPermissions, resourcePermissions ? false : true).build() - } - - if (resourcePermissions && resourceType != 'fictive') { - testResource.accessDataset = getAccessDatasetByPermissions(testResource, client, resourcePermissions, false).build() - } - - return { container: testContainer, resource: testResource } - } - """ - - Scenario Outline: by on resource produces with permissions on container and permissions on resource - Given def testResources = prepareResources(container, resource, type, client) - And url testResources.resource.url - And headers authHeaders(method, client, testResources.resource.url) - When method - Then status - Examples: - | method | client | container | resource | type | status | - | OPTIONS | bob | no | inherited | rdf | 204 | - | OPTIONS | bob | no | inherited | plain | 204 | - | OPTIONS | bob | no | inherited | fictive | 204 | - | OPTIONS | bob | no | inherited | container | 204 | - | OPTIONS | bob | no | R | rdf | 204 | - | OPTIONS | bob | no | R | plain | 204 | - | OPTIONS | bob | no | R | fictive | 204 | - | OPTIONS | bob | no | R | container | 204 | - | OPTIONS | bob | R | inherited | rdf | 204 | - | OPTIONS | bob | R | inherited | plain | 204 | - | OPTIONS | bob | R | inherited | fictive | 204 | - | OPTIONS | bob | R | inherited | container | 204 | - | HEAD | bob | no | inherited | rdf | 403 | - | HEAD | bob | no | inherited | plain | 403 | - | HEAD | bob | no | inherited | fictive | 403 | - | HEAD | bob | no | inherited | container | 403 | - | HEAD | bob | no | R | rdf | 200 | - | HEAD | bob | no | R | plain | 200 | - #| HEAD | bob | no | R | fictive | 404 | - | HEAD | bob | no | R | container | 200 | - | HEAD | bob | R | inherited | rdf | 200 | - | HEAD | bob | R | inherited | plain | 200 | - | HEAD | bob | R | inherited | fictive | 404 | - | HEAD | bob | R | inherited | container | 200 | - | GET | bob | no | inherited | rdf | 403 | - | GET | bob | no | inherited | plain | 403 | - | GET | bob | no | inherited | fictive | 403 | - | GET | bob | no | inherited | container | 403 | - | GET | bob | no | R | rdf | 200 | - | GET | bob | no | R | plain | 200 | - #| GET | bob | no | R | fictive | 404 | - | GET | bob | no | R | container | 200 | - | GET | bob | R | inherited | rdf | 200 | - | GET | bob | R | inherited | plain | 200 | - | GET | bob | R | inherited | fictive | 404 | - | GET | bob | R | inherited | container | 200 | - | GET | bob | R | W | rdf | 403 | - | GET | bob | R | W | plain | 403 | - | GET | bob | R | W | fictive | 403 | - | GET | bob | R | W | container | 403 | - - Scenario Outline: by on container produces with permissions on container and permissions on resource - Given def testResources = prepareResources(container, resource, type, client) - And url testResources.container.url - And headers authHeaders(method, client, testResources.container.url) - And header Content-Type = 'text/turtle' - And request '@prefix rdfs: . <> rdfs:comment "Bob added this.".' - When method - Then status - Examples: - | method | client | container | resource | type | status | - | POST | bob | no | inherited | fictive | 403 | - | POST | bob | no | R | fictive | 403 | - | POST | bob | A | inherited | fictive | 403 | - | POST | bob | A | R | fictive | 201 | - | POST | bob | RA | inherited | fictive | 403 | - | POST | bob | RA | R | fictive | 201 | - | PUT | bob | no | inherited | fictive | 403 | - | PUT | bob | R | inherited | fictive | 403 | - | PUT | bob | W | inherited | fictive | 403 | - - Scenario Outline: by on resource produces with permissions on container and permissions on resource - Given def testResources = prepareResources(container, resource, type, client) - And url testResources.resource.url - And headers authHeaders(method, client, testResources.resource.url) - And header Content-Type = 'text/plain' - And request "Bob's text" - When method - Then status - Examples: - | method | client | container | resource | type | status | - | PUT | bob | no | inherited | plain | 403 | - | PUT | bob | no | inherited | fictive | 403 | - | PUT | bob | no | R | plain | 403 | - | PUT | bob | no | R | fictive | 403 | - | PUT | bob | no | A | plain | 403 | - | PUT | bob | no | A | fictive | 403 | - | PUT | bob | no | W | plain | 205 | - | PUT | bob | no | W | fictive | 403 | - | PUT | bob | R | inherited | plain | 403 | - | PUT | bob | R | inherited | fictive | 403 | - | PUT | bob | A | inherited | plain | 403 | - | PUT | bob | A | inherited | fictive | 403 | - | PUT | bob | W | inherited | plain | 205 | - #| PUT | bob | W | inherited | fictive | 201 | - | PUT | bob | A | W | plain | 205 | - #| PUT | bob | A | W | fictive | 201 | - | POST | bob | no | inherited | plain | 403 | - | POST | bob | no | inherited | fictive | 403 | - | POST | bob | no | R | plain | 403 | - | POST | bob | no | R | fictive | 403 | - | POST | bob | no | A | plain | 405 | - | POST | bob | no | A | fictive | 403 | - | POST | bob | no | W | plain | 405 | - | POST | bob | no | W | fictive | 403 | - | POST | bob | R | inherited | plain | 403 | - | POST | bob | R | inherited | fictive | 404 | - | POST | bob | A | inherited | plain | 405 | - | POST | bob | A | inherited | fictive | 404 | - | POST | bob | W | inherited | plain | 405 | - #| POST | bob | W | inherited | fictive | 201 | - | POST | bob | A | W | plain | 405 | - #| POST | bob | A | W | fictive | 201 | diff --git a/web-access-control/protected-operation/access-permissions-public.feature b/web-access-control/protected-operation/access-permissions-public.feature deleted file mode 100644 index 7ee55f3..0000000 --- a/web-access-control/protected-operation/access-permissions-public.feature +++ /dev/null @@ -1,171 +0,0 @@ -Feature: Access permissions and return codes for public reflect container and resource permissions - Background: Prepare functions for generating resources for test cases - * def authHeaders = (method, client, url) => client == 'public' ? {} : clients[client].getAuthHeaders(method, url) - * def prepareResources = - """ - function (containerModes, resourceModes, resourceType, client) { - - // containerModes, resourceModes = 'RWAC' or any combination thereof, or nothing for no permissions - - const resolvePermissions = function(modes) { - return modes - ? Object.entries({ R: 'read', W: 'write', A: 'append', C: 'control' }).filter(([mode, permission]) => modes.includes(mode)).map(([mode, permission]) => permission) - : [] - } - - const createResourceByType = function(containerToCreateIn, typeToCreate) { - switch (typeToCreate) { - case 'plain': - return containerToCreateIn.createResource('.txt', 'Hello', 'text/plain') - case 'fictive': - return containerToCreateIn.reserveResource('.txt') - case 'rdf': - return containerToCreateIn.createResource('.ttl', karate.readAsString('../fixtures/example.ttl'), 'text/turtle') - case 'container': - return containerToCreateIn.createContainer() - } - } - - const getAccessDatasetByPermissions = function(resource, client, permissions, inheritable) { - return inheritable - ? resource.accessDatasetBuilder.setInheritablePublicAccess(resource.url, permissions) - : resource.accessDatasetBuilder.setPublicAccess(resource.url, permissions) - //return inheritable - // ? resource.accessDatasetBuilder.setInheritableAuthenticatedAccess(resource.url, permissions) - // : resource.accessDatasetBuilder.setAuthenticatedAccess(resource.url, permissions) - //return inheritable - // ? resource.accessDatasetBuilder.setInheritableAgentAccess(resource.url, webIds[client], permissions) - // : resource.accessDatasetBuilder.setAgentAccess(resource.url, webIds[client], permissions) - } - - const testContainer = rootTestContainer.createContainer() - const testResource = createResourceByType(testContainer, resourceType) - - const containerPermissions = resolvePermissions(containerModes) - const resourcePermissions = resourceModes == 'inherited' ? undefined : resolvePermissions(resourceModes) - - // console.log(`Container: ${containerPermissions}, Resource: ${resourcePermissions}`) - - if (containerPermissions) { - testContainer.accessDataset = getAccessDatasetByPermissions(testContainer, client, containerPermissions, resourcePermissions ? false : true).build() - } - - if (resourcePermissions && resourceType != 'fictive') { - testResource.accessDataset = getAccessDatasetByPermissions(testResource, client, resourcePermissions, false).build() - } - - return { container: testContainer, resource: testResource } - } - """ - - Scenario Outline: by on resource produces with permissions on container and permissions on resource - Given def testResources = prepareResources(container, resource, type, client) - And url testResources.resource.url - And headers authHeaders(method, client, testResources.resource.url) - When method - Then status - Examples: - | method | client | container | resource | type | status | - | OPTIONS | public | no | inherited | rdf | 204 | - | OPTIONS | public | no | inherited | plain | 204 | - | OPTIONS | public | no | inherited | fictive | 204 | - | OPTIONS | public | no | inherited | container | 204 | - | OPTIONS | public | no | R | rdf | 204 | - | OPTIONS | public | no | R | plain | 204 | - | OPTIONS | public | no | R | fictive | 204 | - | OPTIONS | public | no | R | container | 204 | - | OPTIONS | public | R | inherited | rdf | 204 | - | OPTIONS | public | R | inherited | plain | 204 | - | OPTIONS | public | R | inherited | fictive | 204 | - | OPTIONS | public | R | inherited | container | 204 | - | HEAD | public | no | inherited | rdf | 401 | - | HEAD | public | no | inherited | plain | 401 | - | HEAD | public | no | inherited | fictive | 401 | - | HEAD | public | no | inherited | container | 401 | - | HEAD | public | no | R | rdf | 200 | - | HEAD | public | no | R | plain | 200 | - #| HEAD | public | no | R | fictive | 404 | - | HEAD | public | no | R | container | 200 | - | HEAD | public | R | inherited | rdf | 200 | - | HEAD | public | R | inherited | plain | 200 | - | HEAD | public | R | inherited | fictive | 404 | - | HEAD | public | R | inherited | container | 200 | - | GET | public | no | inherited | rdf | 401 | - | GET | public | no | inherited | plain | 401 | - | GET | public | no | inherited | fictive | 401 | - | GET | public | no | inherited | container | 401 | - | GET | public | no | R | rdf | 200 | - | GET | public | no | R | plain | 200 | - #| GET | public | no | R | fictive | 404 | - | GET | public | no | R | container | 200 | - | GET | public | R | inherited | rdf | 200 | - | GET | public | R | inherited | plain | 200 | - | GET | public | R | inherited | fictive | 404 | - | GET | public | R | inherited | container | 200 | - | GET | public | R | W | rdf | 401 | - | GET | public | R | W | plain | 401 | - | GET | public | R | W | fictive | 401 | - | GET | public | R | W | container | 401 | - - Scenario Outline: by on container produces with permissions on container and permissions on resource - Given def testResources = prepareResources(container, resource, type, client) - And url testResources.container.url - And headers authHeaders(method, client, testResources.container.url) - And header Content-Type = 'text/turtle' - And request '@prefix rdfs: . <> rdfs:comment "Public added this.".' - When method - Then status - Examples: - | method | client | container | resource | type | status | - | POST | public | no | inherited | fictive | 401 | - | POST | public | no | R | fictive | 401 | - | POST | public | A | inherited | fictive | 401 | - | POST | public | A | R | fictive | 201 | - | POST | public | RA | inherited | fictive | 401 | - | POST | public | RA | R | fictive | 201 | - | PUT | public | no | inherited | fictive | 401 | - | PUT | public | R | inherited | fictive | 401 | - | PUT | public | W | inherited | fictive | 401 | - - Scenario Outline: by on resource produces with permissions on container and permissions on resource - Given def testResources = prepareResources(container, resource, type, client) - And url testResources.resource.url - And headers authHeaders(method, client, testResources.resource.url) - And header Content-Type = 'text/plain' - And request "Public's text" - When method - Then status - Examples: - | method | client | container | resource | type | status | - | PUT | public | no | inherited | plain | 401 | - | PUT | public | no | inherited | fictive | 401 | - | PUT | public | no | R | plain | 401 | - | PUT | public | no | R | fictive | 401 | - | PUT | public | no | A | plain | 401 | - | PUT | public | no | A | fictive | 401 | - | PUT | public | no | W | plain | 205 | - | PUT | public | no | W | fictive | 401 | - | PUT | public | R | inherited | plain | 401 | - | PUT | public | R | inherited | fictive | 401 | - | PUT | public | A | inherited | plain | 401 | - | PUT | public | A | inherited | fictive | 401 | - | PUT | public | W | inherited | plain | 205 | - #| PUT | public | W | inherited | fictive | 201 | - | PUT | public | A | W | plain | 205 | - #| PUT | public | A | W | fictive | 201 | - | POST | public | no | inherited | plain | 401 | - | POST | public | no | inherited | fictive | 401 | - | POST | public | no | R | plain | 401 | - | POST | public | no | R | fictive | 401 | - | POST | public | no | A | plain | 405 | - | POST | public | no | A | fictive | 401 | - | POST | public | no | W | plain | 405 | - | POST | public | no | W | fictive | 401 | - | POST | public | R | inherited | plain | 401 | - | POST | public | R | inherited | fictive | 404 | - | POST | public | A | inherited | plain | 405 | - | POST | public | A | inherited | fictive | 404 | - | POST | public | W | inherited | plain | 405 | - #| POST | public | W | inherited | fictive | 201 | - | POST | public | A | W | plain | 405 | - #| POST | public | A | W | fictive | 201 | diff --git a/web-access-control/protected-operation/read-access-agent.feature b/web-access-control/protected-operation/read-access-agent.feature index 3f6e215..b31de72 100644 --- a/web-access-control/protected-operation/read-access-agent.feature +++ b/web-access-control/protected-operation/read-access-agent.feature @@ -1,143 +1,261 @@ Feature: Only authenticated agents can read (and only that) a resource when granted read access # Grant authenticated agents (setAuthenticatedAccess): - # - full access to the parent container (to ensure the tests are specific to the resource) - # - restricted access to the test resources + # - restricted access or no access to the parent container + # - restricted access to the test resources, or inherited access for fictive resources Background: Create test resources with correct access modes - * def authHeaders = (method, url, public) => !public ? clients.bob.getAuthHeaders(method, url) : {} - * def createResources = + * def authHeaders = + """ + function (method, url, agent) { + const agentLowerCase = agent.toLowerCase() + return agentLowerCase != 'public' ? clients[agentLowerCase].getAuthHeaders(method, url) : {} + } + """ + * def resourcePermissions = """ function (modes) { + if (modes && modes != 'inherited' && modes != 'no') { + return Object.entries({ R: 'read', W: 'write', A: 'append', C: 'control' }) + .filter(([mode, permission]) => modes.includes(mode)) + .map(([mode, permission]) => permission) + } + return undefined + } + """ + * def resourceEntry = + """ + function (container, type) { + switch (type) { + case 'plain': + return container.createResource('.txt', 'Hello', 'text/plain') + case 'fictive': + return container.reserveResource('.txt') + case 'rdf': + return container.createResource('.ttl', karate.readAsString('../fixtures/example.ttl'), 'text/turtle') + case 'container': + return container.createContainer() + default: + return undefined + } + } + """ + * def createResource = + """ + function (containerModes, resourceModes, resourceType, accessMode) { + + const testContainerPermissions = resourcePermissions(containerModes == 'all' ? 'RWAC' : containerModes) + const testResourcePermissions = resourcePermissions(resourceModes) + + const testContainerInheritablePermissions = resourceModes == 'inherited' + ? testContainerPermissions + : resourceType == 'fictive' + ? testResourcePermissions + : undefined + const testContainer = rootTestContainer.createContainer() + const testResource = resourceEntry(testContainer, resourceType) + testContainer.accessDataset = testContainer.accessDatasetBuilder - .setAuthenticatedAccess(testContainer.url, ['read', 'write', 'append', 'control']) - .setInheritableAuthenticatedAccess(testContainer.url, modes).build() - const plainResource = testContainer.createResource('.txt', 'Hello', 'text/plain') - plainResource.accessDataset = plainResource.accessDatasetBuilder.setAuthenticatedAccess(plainResource.url, modes).build() - const fictiveResource = testContainer.reserveResource('.txt') - const rdfResource = testContainer.createResource('.ttl', karate.readAsString('../fixtures/example.ttl'), 'text/turtle') - rdfResource.accessDataset = rdfResource.accessDatasetBuilder.setAuthenticatedAccess(rdfResource.url, modes).build() - const container = testContainer.createContainer() - container.accessDataset = container.accessDatasetBuilder.setAuthenticatedAccess(container.url, modes).build() - return { plain: plainResource, fictive: fictiveResource, rdf: rdfResource, container: container } + .setAuthenticatedAccess(testContainer.url, testContainerPermissions) + .setInheritableAuthenticatedAccess(testContainer.url, testContainerInheritablePermissions) + .build() + + if (resourceType != 'fictive' && resourceModes != 'inherited') { + testResource.accessDataset = testResource.accessDatasetBuilder + .setAuthenticatedAccess(testResource.url, testResourcePermissions) + .build() + } + + return testResource } """ - # Create 3 test resources with read access for authenticated agents - * def testsR = callonce createResources ['read'] - # Create 3 test resources with append, write, control access for authenticated agents - * def testsAWC = callonce createResources ['append', 'write', 'control'] - Scenario Outline: read a resource () to which an authenticated agent has access - Given url tests[type].url - And headers authHeaders(method, tests[type].url, public) + Scenario Outline: read a resource (), when an authenticated agent has access to the container and access to the resource + * def testResource = createResource(container, resource, type) + Given url testResource.url + And headers authHeaders(method, testResource.url, agent) When method Then status Examples: - | agent | type | mode | method | public! | status | - | Bob can | plain | R | GET | false | 200 | - | Bob can | fictive | R | GET | false | 404 | - | Bob can | rdf | R | GET | false | 200 | - | Bob can | container | R | GET | false | 200 | - | Bob can | plain | R | HEAD | false | 200 | - | Bob can | fictive | R | HEAD | false | 404 | - | Bob can | rdf | R | HEAD | false | 200 | - | Bob can | container | R | HEAD | false | 200 | - | Public cannot | plain | R | GET | true | 401 | - | Public cannot | fictive | R | GET | true | 401 | - | Public cannot | rdf | R | GET | true | 401 | - | Public cannot | container | R | GET | true | 401 | - | Public cannot | plain | R | HEAD | true | 401 | - | Public cannot | fictive | R | HEAD | true | 401 | - | Public cannot | rdf | R | HEAD | true | 401 | - | Public cannot | container | R | HEAD | true | 401 | - | Bob cannot | plain | AWC | GET | false | 403 | - | Bob cannot | fictive | AWC | GET | false | 403 | - | Bob cannot | rdf | AWC | GET | false | 403 | - | Bob cannot | container | AWC | GET | false | 403 | - | Bob cannot | plain | AWC | HEAD | false | 403 | - | Bob cannot | fictive | AWC | HEAD | false | 403 | - | Bob cannot | rdf | AWC | HEAD | false | 403 | - | Bob cannot | container | AWC | HEAD | false | 403 | - | Public cannot | plain | AWC | GET | true | 401 | - | Public cannot | fictive | AWC | GET | true | 401 | - | Public cannot | rdf | AWC | GET | true | 401 | - | Public cannot | container | AWC | GET | true | 401 | - | Public cannot | plain | AWC | HEAD | true | 401 | - | Public cannot | fictive | AWC | HEAD | true | 401 | - | Public cannot | rdf | AWC | HEAD | true | 401 | - | Public cannot | container | AWC | HEAD | true | 401 | + | agent | result | method | type | container | resource | status | + | Bob | can | GET | plain | no | R | 200 | + | Bob | can | GET | plain | R | inherited | 200 | + | Bob | can | GET | fictive | no | R | 404 | + | Bob | can | GET | fictive | R | inherited | 404 | + | Bob | can | GET | rdf | no | R | 200 | + | Bob | can | GET | rdf | R | inherited | 200 | + | Bob | can | GET | container | no | R | 200 | + | Bob | can | GET | container | R | inherited | 200 | + | Bob | can | HEAD | plain | no | R | 200 | + | Bob | can | HEAD | plain | R | inherited | 200 | + | Bob | can | HEAD | fictive | no | R | 404 | + | Bob | can | HEAD | fictive | R | inherited | 404 | + | Bob | can | HEAD | rdf | no | R | 200 | + | Bob | can | HEAD | rdf | R | inherited | 200 | + | Bob | can | HEAD | container | no | R | 200 | + | Bob | can | HEAD | container | R | inherited | 200 | + | Public | cannot | GET | plain | no | R | 401 | + | Public | cannot | GET | plain | R | inherited | 401 | + | Public | cannot | GET | fictive | no | R | 401 | + | Public | cannot | GET | fictive | R | inherited | 401 | + | Public | cannot | GET | rdf | no | R | 401 | + | Public | cannot | GET | rdf | R | inherited | 401 | + | Public | cannot | GET | container | no | R | 401 | + | Public | cannot | GET | container | R | inherited | 401 | + | Public | cannot | HEAD | plain | no | R | 401 | + | Public | cannot | HEAD | plain | R | inherited | 401 | + | Public | cannot | HEAD | fictive | no | R | 401 | + | Public | cannot | HEAD | fictive | R | inherited | 401 | + | Public | cannot | HEAD | rdf | no | R | 401 | + | Public | cannot | HEAD | rdf | R | inherited | 401 | + | Public | cannot | HEAD | container | no | R | 401 | + | Public | cannot | HEAD | container | R | inherited | 401 | + | Bob | cannot | GET | plain | no | AWC | 403 | + | Bob | cannot | GET | plain | AWC | inherited | 403 | + | Bob | cannot | GET | fictive | no | AWC | 403 | + | Bob | cannot | GET | fictive | AWC | inherited | 403 | + | Bob | cannot | GET | rdf | no | AWC | 403 | + | Bob | cannot | GET | rdf | AWC | inherited | 403 | + | Bob | cannot | GET | container | no | AWC | 403 | + | Bob | cannot | GET | container | AWC | inherited | 403 | + | Bob | cannot | HEAD | plain | no | AWC | 403 | + | Bob | cannot | HEAD | plain | AWC | inherited | 403 | + | Bob | cannot | HEAD | fictive | no | AWC | 403 | + | Bob | cannot | HEAD | fictive | AWC | inherited | 403 | + | Bob | cannot | HEAD | rdf | no | AWC | 403 | + | Bob | cannot | HEAD | rdf | AWC | inherited | 403 | + | Bob | cannot | HEAD | container | no | AWC | 403 | + | Bob | cannot | HEAD | container | AWC | inherited | 403 | + | Public | cannot | GET | plain | no | AWC | 401 | + | Public | cannot | GET | plain | AWC | inherited | 401 | + | Public | cannot | GET | fictive | no | AWC | 401 | + | Public | cannot | GET | fictive | AWC | inherited | 401 | + | Public | cannot | GET | rdf | no | AWC | 401 | + | Public | cannot | GET | rdf | AWC | inherited | 401 | + | Public | cannot | GET | container | no | AWC | 401 | + | Public | cannot | GET | container | AWC | inherited | 401 | + | Public | cannot | HEAD | plain | no | AWC | 401 | + | Public | cannot | HEAD | plain | AWC | inherited | 401 | + | Public | cannot | HEAD | fictive | no | AWC | 401 | + | Public | cannot | HEAD | fictive | AWC | inherited | 401 | + | Public | cannot | HEAD | rdf | no | AWC | 401 | + | Public | cannot | HEAD | rdf | AWC | inherited | 401 | + | Public | cannot | HEAD | container | no | AWC | 401 | + | Public | cannot | HEAD | container | AWC | inherited | 401 | - Scenario Outline: cannot to a resource to which an authenticated agent has access - Given url tests[type].url - And headers authHeaders(method, tests[type].url, public) + Scenario Outline: to a resource, when an authenticated agent has access to the container and access to the resource + * def testResource = createResource(container, resource, type) + Given url testResource.url + And headers authHeaders(method, testResource.url, agent) And header Content-Type = 'text/turtle' And request '@prefix rdfs: . <> rdfs:comment "Bob added this.".' When method Then status Examples: - | agent | type | mode | method | public! | status | - | Bob | rdf | R | PUT | false | 403 | - | Bob | fictive | R | PUT | false | 403 | - | Bob | container | R | PUT | false | 403 | - | Bob | rdf | R | POST | false | 403 | - | Bob | fictive | R | POST | false | 404 | - | Bob | container | R | POST | false | 403 | - | Public | rdf | R | PUT | true | 401 | - | Public | fictive | R | PUT | true | 401 | - | Public | container | R | PUT | true | 401 | - | Public | rdf | R | POST | true | 401 | - | Public | fictive | R | POST | true | 401 | - | Public | container | R | POST | true | 401 | + | agent | result | method | type | container | resource | status | + | Bob | cannot | PUT | rdf | no | R | 403 | + | Bob | cannot | PUT | rdf | R | inherited | 403 | + | Bob | cannot | PUT | fictive | no | R | 403 | + | Bob | cannot | PUT | fictive | R | inherited | 403 | + | Bob | cannot | PUT | container | no | R | 403 | + | Bob | cannot | PUT | container | R | inherited | 403 | + | Bob | cannot | POST | rdf | no | R | 403 | + | Bob | cannot | POST | rdf | R | inherited | 403 | + | Bob | cannot | POST | fictive | no | R | 404 | + | Bob | cannot | POST | fictive | R | inherited | 404 | + | Bob | cannot | POST | container | no | R | 403 | + | Bob | cannot | POST | container | R | inherited | 403 | + | Public | cannot | PUT | rdf | no | R | 401 | + | Public | cannot | PUT | rdf | R | inherited | 401 | + | Public | cannot | PUT | fictive | no | R | 401 | + | Public | cannot | PUT | fictive | R | inherited | 401 | + | Public | cannot | PUT | container | no | R | 401 | + | Public | cannot | PUT | container | R | inherited | 401 | + | Public | cannot | POST | rdf | no | R | 401 | + | Public | cannot | POST | rdf | R | inherited | 401 | + | Public | cannot | POST | fictive | no | R | 401 | + | Public | cannot | POST | fictive | R | inherited | 401 | + | Public | cannot | POST | container | no | R | 401 | + | Public | cannot | POST | container | R | inherited | 401 | - Scenario Outline: cannot to a resource to which an authenticated agent has access - Given url tests[type].url - And headers authHeaders(method, tests[type].url, public) + Scenario Outline: to a resource, when an authenticated agent has access to the container and access to the resource + * def testResource = createResource(container, resource, type) + Given url testResource.url + And headers authHeaders(method, testResource.url, agent) And header Content-Type = 'text/n3' And request '@prefix solid: . _:insert a solid:InsertDeletePatch; solid:inserts { <> a . }.' When method Then status Examples: - | agent | type | mode | method | public! | status | - | Bob | rdf | R | PATCH | false | 403 | - | Bob | fictive | R | PATCH | false | 403 | - | Bob | container | R | PATCH | false | 403 | - | Public | rdf | R | PATCH | true | 401 | - | Public | fictive | R | PATCH | true | 401 | - | Public | container | R | PATCH | true | 401 | + | agent | result | method | type | container | resource | status | + | Bob | cannot | PATCH | rdf | no | R | 403 | + | Bob | cannot | PATCH | rdf | R | inherited | 403 | + | Bob | cannot | PATCH | fictive | no | R | 403 | + | Bob | cannot | PATCH | fictive | R | inherited | 403 | + | Bob | cannot | PATCH | container | no | R | 403 | + | Bob | cannot | PATCH | container | R | inherited | 403 | + | Public | cannot | PATCH | rdf | no | R | 401 | + | Public | cannot | PATCH | rdf | R | inherited | 401 | + | Public | cannot | PATCH | fictive | no | R | 401 | + | Public | cannot | PATCH | fictive | R | inherited | 401 | + | Public | cannot | PATCH | container | no | R | 401 | + | Public | cannot | PATCH | container | R | inherited | 401 | - Scenario Outline: cannot to a resource to which an authenticated agent has access - Given url tests[type].url - And headers authHeaders(method, tests[type].url, public) + Scenario Outline: to a resource, when an authenticated agent has access to the container and access to the resource + * def testResource = createResource(container, resource, type) + Given url testResource.url + And headers authHeaders(method, testResource.url, agent) And header Content-Type = 'text/plain' And request "Bob's text" When method Then match contains responseStatus Examples: - | agent | type | mode | method | public! | status | - | Bob | plain | R | PUT | false | [403] | - | Bob | plain | R | POST | false | [403] | - | Bob | plain | R | PATCH | false | [403, 405, 415] | - | Bob | fictive | R | PUT | false | [403] | - | Bob | fictive | R | POST | false | [404] | - | Bob | fictive | R | PATCH | false | [403, 405, 415] | - | Public | plain | R | PUT | true | [401] | - | Public | plain | R | POST | true | [401] | - | Public | plain | R | PATCH | true | [401, 405, 415] | - | Public | fictive | R | PUT | true | [401] | - | Public | fictive | R | POST | true | [401] | - | Public | fictive | R | PATCH | true | [401, 405, 415] | + | agent | result | method | type | container | resource | status | + | Bob | cannot | PUT | plain | no | R | [403] | + | Bob | cannot | PUT | plain | R | inherited | [403] | + | Bob | cannot | PUT | fictive | no | R | [403] | + | Bob | cannot | PUT | fictive | R | inherited | [403] | + | Bob | cannot | POST | plain | no | R | [403] | + | Bob | cannot | POST | plain | R | inherited | [403] | + | Bob | cannot | POST | fictive | no | R | [404] | + | Bob | cannot | POST | fictive | R | inherited | [404] | + | Bob | cannot | PATCH | plain | no | R | [403, 405, 415] | + | Bob | cannot | PATCH | plain | R | inherited | [403, 405, 415] | + | Bob | cannot | PATCH | fictive | no | R | [403, 405, 415] | + | Bob | cannot | PATCH | fictive | R | inherited | [403, 405, 415] | + | Public | cannot | PUT | plain | no | R | [401] | + | Public | cannot | PUT | plain | R | inherited | [401] | + | Public | cannot | PUT | fictive | no | R | [401] | + | Public | cannot | PUT | fictive | R | inherited | [401] | + | Public | cannot | POST | plain | no | R | [401] | + | Public | cannot | POST | plain | R | inherited | [401] | + | Public | cannot | POST | fictive | no | R | [401] | + | Public | cannot | POST | fictive | R | inherited | [401] | + | Public | cannot | PATCH | plain | no | R | [401, 405, 415] | + | Public | cannot | PATCH | plain | R | inherited | [401, 405, 415] | + | Public | cannot | PATCH | fictive | no | R | [401, 405, 415] | + | Public | cannot | PATCH | fictive | R | inherited | [401, 405, 415] | - Scenario Outline: cannot a resource to which an authenticated agent has access - Given url tests[type].url - And headers authHeaders(method, tests[type].url, public) + Scenario Outline: a resource, when an authenticated agent has access to the container and access to the resource + * def testResource = createResource(container, resource, type) + Given url testResource.url + And headers authHeaders(method, testResource.url, agent) When method Then status Examples: - | agent | type | mode | method | public! | status | - | Bob | plain | R | DELETE | false | 403 | - | Bob | fictive | R | DELETE | false | 404 | - | Bob | rdf | R | DELETE | false | 403 | - | Bob | container | R | DELETE | false | 403 | - | Public | plain | R | DELETE | true | 401 | - | Public | fictive | R | DELETE | true | 401 | - | Public | rdf | R | DELETE | true | 401 | - | Public | container | R | DELETE | true | 401 | + | agent | result | method | type | container | resource | status | + | Bob | cannot | DELETE | plain | no | R | 403 | + | Bob | cannot | DELETE | plain | R | inherited | 403 | + | Bob | cannot | DELETE | fictive | no | R | 404 | + | Bob | cannot | DELETE | fictive | R | inherited | 404 | + | Bob | cannot | DELETE | rdf | no | R | 403 | + | Bob | cannot | DELETE | rdf | R | inherited | 403 | + | Bob | cannot | DELETE | container | no | R | 403 | + | Bob | cannot | DELETE | container | R | inherited | 403 | + | Public | cannot | DELETE | plain | no | R | 401 | + | Public | cannot | DELETE | plain | R | inherited | 401 | + | Public | cannot | DELETE | fictive | no | R | 401 | + | Public | cannot | DELETE | fictive | R | inherited | 401 | + | Public | cannot | DELETE | rdf | no | R | 401 | + | Public | cannot | DELETE | rdf | R | inherited | 401 | + | Public | cannot | DELETE | container | no | R | 401 | + | Public | cannot | DELETE | container | R | inherited | 401 | diff --git a/web-access-control/protected-operation/read-access-bob.feature b/web-access-control/protected-operation/read-access-bob.feature index cbe7e35..5d2db4d 100644 --- a/web-access-control/protected-operation/read-access-bob.feature +++ b/web-access-control/protected-operation/read-access-bob.feature @@ -1,143 +1,262 @@ Feature: Only Bob can read (and only that) a resource when granted read access # Grant a specific agent (setAgentAccess): - # - full access to the parent container (to ensure the tests are specific to the resource) - # - restricted access to the test resources + # - restricted access or no access to the parent container + # - restricted access to the test resources, or inherited access for fictive resources Background: Create test resources with correct access modes - * def authHeaders = (method, url, public) => !public ? clients.bob.getAuthHeaders(method, url) : {} - * def createResources = + * def authHeaders = + """ + function (method, url, agent) { + const agentLowerCase = agent.toLowerCase() + return agentLowerCase != 'public' ? clients[agentLowerCase].getAuthHeaders(method, url) : {} + } + """ + * def resourcePermissions = """ function (modes) { + if (modes && modes != 'inherited' && modes != 'no') { + return Object.entries({ R: 'read', W: 'write', A: 'append', C: 'control' }) + .filter(([mode, permission]) => modes.includes(mode)) + .map(([mode, permission]) => permission) + } + return undefined + } + """ + * def resourceEntry = + """ + function (container, type) { + switch (type) { + case 'plain': + return container.createResource('.txt', 'Hello', 'text/plain') + case 'fictive': + return container.reserveResource('.txt') + case 'rdf': + return container.createResource('.ttl', karate.readAsString('../fixtures/example.ttl'), 'text/turtle') + case 'container': + return container.createContainer() + default: + return undefined + } + } + """ + * def createResource = + """ + function (containerModes, resourceModes, resourceType, accessMode) { + + const agentWebId = webIds.bob + const testContainerPermissions = resourcePermissions(containerModes == 'all' ? 'RWAC' : containerModes) + const testResourcePermissions = resourcePermissions(resourceModes) + + const testContainerInheritablePermissions = resourceModes == 'inherited' + ? testContainerPermissions + : resourceType == 'fictive' + ? testResourcePermissions + : undefined + const testContainer = rootTestContainer.createContainer() + const testResource = resourceEntry(testContainer, resourceType) + testContainer.accessDataset = testContainer.accessDatasetBuilder - .setAgentAccess(testContainer.url, webIds.bob, ['read', 'write', 'append', 'control']) - .setInheritableAgentAccess(testContainer.url, webIds.bob, modes).build() - const plainResource = testContainer.createResource('.txt', 'Hello', 'text/plain') - plainResource.accessDataset = plainResource.accessDatasetBuilder.setAgentAccess(plainResource.url, webIds.bob, modes).build() - const fictiveResource = testContainer.reserveResource('.txt') - const rdfResource = testContainer.createResource('.ttl', karate.readAsString('../fixtures/example.ttl'), 'text/turtle') - rdfResource.accessDataset = rdfResource.accessDatasetBuilder.setAgentAccess(rdfResource.url, webIds.bob, modes).build() - const container = testContainer.createContainer() - container.accessDataset = container.accessDatasetBuilder.setAgentAccess(container.url, webIds.bob, modes).build() - return { plain: plainResource, fictive: fictiveResource, rdf: rdfResource, container: container } + .setAgentAccess(testContainer.url, agentWebId, testContainerPermissions) + .setInheritableAgentAccess(testContainer.url, agentWebId, testContainerInheritablePermissions) + .build() + + if (resourceType != 'fictive' && resourceModes != 'inherited') { + testResource.accessDataset = testResource.accessDatasetBuilder + .setAgentAccess(testResource.url, agentWebId, testResourcePermissions) + .build() + } + + return testResource } """ - # Create 3 test resources with read access for Bob - * def testsR = callonce createResources ['read'] - # Create 3 test resources with append, write, control access for Bob - * def testsAWC = callonce createResources ['append', 'write', 'control'] - Scenario Outline: read a resource () to which Bob has access - Given url tests[type].url - And headers authHeaders(method, tests[type].url, public) + Scenario Outline: read a resource (), when Bob has access to the container and access to the resource + * def testResource = createResource(container, resource, type) + Given url testResource.url + And headers authHeaders(method, testResource.url, agent) When method Then status Examples: - | agent | type | mode | method | public! | status | - | Bob can | plain | R | GET | false | 200 | - | Bob can | fictive | R | GET | false | 404 | - | Bob can | rdf | R | GET | false | 200 | - | Bob can | container | R | GET | false | 200 | - | Bob can | plain | R | HEAD | false | 200 | - | Bob can | fictive | R | HEAD | false | 404 | - | Bob can | rdf | R | HEAD | false | 200 | - | Bob can | container | R | HEAD | false | 200 | - | Public cannot | plain | R | GET | true | 401 | - | Public cannot | fictive | R | GET | true | 401 | - | Public cannot | rdf | R | GET | true | 401 | - | Public cannot | container | R | GET | true | 401 | - | Public cannot | plain | R | HEAD | true | 401 | - | Public cannot | fictive | R | HEAD | true | 401 | - | Public cannot | rdf | R | HEAD | true | 401 | - | Public cannot | container | R | HEAD | true | 401 | - | Bob cannot | plain | AWC | GET | false | 403 | - | Bob cannot | fictive | AWC | GET | false | 403 | - | Bob cannot | rdf | AWC | GET | false | 403 | - | Bob cannot | container | AWC | GET | false | 403 | - | Bob cannot | plain | AWC | HEAD | false | 403 | - | Bob cannot | fictive | AWC | HEAD | false | 403 | - | Bob cannot | rdf | AWC | HEAD | false | 403 | - | Bob cannot | container | AWC | HEAD | false | 403 | - | Public cannot | plain | AWC | GET | true | 401 | - | Public cannot | fictive | AWC | GET | true | 401 | - | Public cannot | rdf | AWC | GET | true | 401 | - | Public cannot | container | AWC | GET | true | 401 | - | Public cannot | plain | AWC | HEAD | true | 401 | - | Public cannot | fictive | AWC | HEAD | true | 401 | - | Public cannot | rdf | AWC | HEAD | true | 401 | - | Public cannot | container | AWC | HEAD | true | 401 | + | agent | result | method | type | container | resource | status | + | Bob | can | GET | plain | no | R | 200 | + | Bob | can | GET | plain | R | inherited | 200 | + | Bob | can | GET | fictive | no | R | 404 | + | Bob | can | GET | fictive | R | inherited | 404 | + | Bob | can | GET | rdf | no | R | 200 | + | Bob | can | GET | rdf | R | inherited | 200 | + | Bob | can | GET | container | no | R | 200 | + | Bob | can | GET | container | R | inherited | 200 | + | Bob | can | HEAD | plain | no | R | 200 | + | Bob | can | HEAD | plain | R | inherited | 200 | + | Bob | can | HEAD | fictive | no | R | 404 | + | Bob | can | HEAD | fictive | R | inherited | 404 | + | Bob | can | HEAD | rdf | no | R | 200 | + | Bob | can | HEAD | rdf | R | inherited | 200 | + | Bob | can | HEAD | container | no | R | 200 | + | Bob | can | HEAD | container | R | inherited | 200 | + | Public | cannot | GET | plain | no | R | 401 | + | Public | cannot | GET | plain | R | inherited | 401 | + | Public | cannot | GET | fictive | no | R | 401 | + | Public | cannot | GET | fictive | R | inherited | 401 | + | Public | cannot | GET | rdf | no | R | 401 | + | Public | cannot | GET | rdf | R | inherited | 401 | + | Public | cannot | GET | container | no | R | 401 | + | Public | cannot | GET | container | R | inherited | 401 | + | Public | cannot | HEAD | plain | no | R | 401 | + | Public | cannot | HEAD | plain | R | inherited | 401 | + | Public | cannot | HEAD | fictive | no | R | 401 | + | Public | cannot | HEAD | fictive | R | inherited | 401 | + | Public | cannot | HEAD | rdf | no | R | 401 | + | Public | cannot | HEAD | rdf | R | inherited | 401 | + | Public | cannot | HEAD | container | no | R | 401 | + | Public | cannot | HEAD | container | R | inherited | 401 | + | Bob | cannot | GET | plain | no | AWC | 403 | + | Bob | cannot | GET | plain | AWC | inherited | 403 | + | Bob | cannot | GET | fictive | no | AWC | 403 | + | Bob | cannot | GET | fictive | AWC | inherited | 403 | + | Bob | cannot | GET | rdf | no | AWC | 403 | + | Bob | cannot | GET | rdf | AWC | inherited | 403 | + | Bob | cannot | GET | container | no | AWC | 403 | + | Bob | cannot | GET | container | AWC | inherited | 403 | + | Bob | cannot | HEAD | plain | no | AWC | 403 | + | Bob | cannot | HEAD | plain | AWC | inherited | 403 | + | Bob | cannot | HEAD | fictive | no | AWC | 403 | + | Bob | cannot | HEAD | fictive | AWC | inherited | 403 | + | Bob | cannot | HEAD | rdf | no | AWC | 403 | + | Bob | cannot | HEAD | rdf | AWC | inherited | 403 | + | Bob | cannot | HEAD | container | no | AWC | 403 | + | Bob | cannot | HEAD | container | AWC | inherited | 403 | + | Public | cannot | GET | plain | no | AWC | 401 | + | Public | cannot | GET | plain | AWC | inherited | 401 | + | Public | cannot | GET | fictive | no | AWC | 401 | + | Public | cannot | GET | fictive | AWC | inherited | 401 | + | Public | cannot | GET | rdf | no | AWC | 401 | + | Public | cannot | GET | rdf | AWC | inherited | 401 | + | Public | cannot | GET | container | no | AWC | 401 | + | Public | cannot | GET | container | AWC | inherited | 401 | + | Public | cannot | HEAD | plain | no | AWC | 401 | + | Public | cannot | HEAD | plain | AWC | inherited | 401 | + | Public | cannot | HEAD | fictive | no | AWC | 401 | + | Public | cannot | HEAD | fictive | AWC | inherited | 401 | + | Public | cannot | HEAD | rdf | no | AWC | 401 | + | Public | cannot | HEAD | rdf | AWC | inherited | 401 | + | Public | cannot | HEAD | container | no | AWC | 401 | + | Public | cannot | HEAD | container | AWC | inherited | 401 | - Scenario Outline: cannot to a resource to which Bob has access - Given url tests[type].url - And headers authHeaders(method, tests[type].url, public) + Scenario Outline: to a resource, when Bob has access to the container and access to the resource + * def testResource = createResource(container, resource, type) + Given url testResource.url + And headers authHeaders(method, testResource.url, agent) And header Content-Type = 'text/turtle' And request '@prefix rdfs: . <> rdfs:comment "Bob added this.".' When method Then status Examples: - | agent | type | mode | method | public! | status | - | Bob | rdf | R | PUT | false | 403 | - | Bob | fictive | R | PUT | false | 403 | - | Bob | container | R | PUT | false | 403 | - | Bob | rdf | R | POST | false | 403 | - | Bob | fictive | R | POST | false | 404 | - | Bob | container | R | POST | false | 403 | - | Public | rdf | R | PUT | true | 401 | - | Public | fictive | R | PUT | true | 401 | - | Public | container | R | PUT | true | 401 | - | Public | rdf | R | POST | true | 401 | - | Public | fictive | R | POST | true | 401 | - | Public | container | R | POST | true | 401 | + | agent | result | method | type | container | resource | status | + | Bob | cannot | PUT | rdf | no | R | 403 | + | Bob | cannot | PUT | rdf | R | inherited | 403 | + | Bob | cannot | PUT | fictive | no | R | 403 | + | Bob | cannot | PUT | fictive | R | inherited | 403 | + | Bob | cannot | PUT | container | no | R | 403 | + | Bob | cannot | PUT | container | R | inherited | 403 | + | Bob | cannot | POST | rdf | no | R | 403 | + | Bob | cannot | POST | rdf | R | inherited | 403 | + | Bob | cannot | POST | fictive | no | R | 404 | + | Bob | cannot | POST | fictive | R | inherited | 404 | + | Bob | cannot | POST | container | no | R | 403 | + | Bob | cannot | POST | container | R | inherited | 403 | + | Public | cannot | PUT | rdf | no | R | 401 | + | Public | cannot | PUT | rdf | R | inherited | 401 | + | Public | cannot | PUT | fictive | no | R | 401 | + | Public | cannot | PUT | fictive | R | inherited | 401 | + | Public | cannot | PUT | container | no | R | 401 | + | Public | cannot | PUT | container | R | inherited | 401 | + | Public | cannot | POST | rdf | no | R | 401 | + | Public | cannot | POST | rdf | R | inherited | 401 | + | Public | cannot | POST | fictive | no | R | 401 | + | Public | cannot | POST | fictive | R | inherited | 401 | + | Public | cannot | POST | container | no | R | 401 | + | Public | cannot | POST | container | R | inherited | 401 | - Scenario Outline: cannot to a resource to which Bob has access - Given url tests[type].url - And headers authHeaders(method, tests[type].url, public) + Scenario Outline: to a resource, when Bob has access to the container and access to the resource + * def testResource = createResource(container, resource, type) + Given url testResource.url + And headers authHeaders(method, testResource.url, agent) And header Content-Type = 'text/n3' And request '@prefix solid: . _:insert a solid:InsertDeletePatch; solid:inserts { <> a . }.' When method Then status Examples: - | agent | type | mode | method | public! | status | - | Bob | rdf | R | PATCH | false | 403 | - | Bob | fictive | R | PATCH | false | 403 | - | Bob | container | R | PATCH | false | 403 | - | Public | rdf | R | PATCH | true | 401 | - | Public | fictive | R | PATCH | true | 401 | - | Public | container | R | PATCH | true | 401 | + | agent | result | method | type | container | resource | status | + | Bob | cannot | PATCH | rdf | no | R | 403 | + | Bob | cannot | PATCH | rdf | R | inherited | 403 | + | Bob | cannot | PATCH | fictive | no | R | 403 | + | Bob | cannot | PATCH | fictive | R | inherited | 403 | + | Bob | cannot | PATCH | container | no | R | 403 | + | Bob | cannot | PATCH | container | R | inherited | 403 | + | Public | cannot | PATCH | rdf | no | R | 401 | + | Public | cannot | PATCH | rdf | R | inherited | 401 | + | Public | cannot | PATCH | fictive | no | R | 401 | + | Public | cannot | PATCH | fictive | R | inherited | 401 | + | Public | cannot | PATCH | container | no | R | 401 | + | Public | cannot | PATCH | container | R | inherited | 401 | - Scenario Outline: cannot to a resource to which Bob has access - Given url tests[type].url - And headers authHeaders(method, tests[type].url, public) + Scenario Outline: to a resource, when Bob has access to the container and access to the resource + * def testResource = createResource(container, resource, type) + Given url testResource.url + And headers authHeaders(method, testResource.url, agent) And header Content-Type = 'text/plain' And request "Bob's text" When method Then match contains responseStatus Examples: - | agent | type | mode | method | public! | status | - | Bob | plain | R | PUT | false | [403] | - | Bob | plain | R | POST | false | [403] | - | Bob | plain | R | PATCH | false | [403, 405, 415] | - | Bob | fictive | R | PUT | false | [403] | - | Bob | fictive | R | POST | false | [404] | - | Bob | fictive | R | PATCH | false | [403, 405, 415] | - | Public | plain | R | PUT | true | [401] | - | Public | plain | R | POST | true | [401] | - | Public | plain | R | PATCH | true | [401, 405, 415] | - | Public | fictive | R | PUT | true | [401] | - | Public | fictive | R | POST | true | [401] | - | Public | fictive | R | PATCH | true | [401, 405, 415] | + | agent | result | method | type | container | resource | status | + | Bob | cannot | PUT | plain | no | R | [403] | + | Bob | cannot | PUT | plain | R | inherited | [403] | + | Bob | cannot | PUT | fictive | no | R | [403] | + | Bob | cannot | PUT | fictive | R | inherited | [403] | + | Bob | cannot | POST | plain | no | R | [403] | + | Bob | cannot | POST | plain | R | inherited | [403] | + | Bob | cannot | POST | fictive | no | R | [404] | + | Bob | cannot | POST | fictive | R | inherited | [404] | + | Bob | cannot | PATCH | plain | no | R | [403, 405, 415] | + | Bob | cannot | PATCH | plain | R | inherited | [403, 405, 415] | + | Bob | cannot | PATCH | fictive | no | R | [403, 405, 415] | + | Bob | cannot | PATCH | fictive | R | inherited | [403, 405, 415] | + | Public | cannot | PUT | plain | no | R | [401] | + | Public | cannot | PUT | plain | R | inherited | [401] | + | Public | cannot | PUT | fictive | no | R | [401] | + | Public | cannot | PUT | fictive | R | inherited | [401] | + | Public | cannot | POST | plain | no | R | [401] | + | Public | cannot | POST | plain | R | inherited | [401] | + | Public | cannot | POST | fictive | no | R | [401] | + | Public | cannot | POST | fictive | R | inherited | [401] | + | Public | cannot | PATCH | plain | no | R | [401, 405, 415] | + | Public | cannot | PATCH | plain | R | inherited | [401, 405, 415] | + | Public | cannot | PATCH | fictive | no | R | [401, 405, 415] | + | Public | cannot | PATCH | fictive | R | inherited | [401, 405, 415] | - Scenario Outline: cannot a resource to which Bob has access - Given url tests[type].url - And headers authHeaders(method, tests[type].url, public) + Scenario Outline: a resource, when Bob has access to the container and access to the resource + * def testResource = createResource(container, resource, type) + Given url testResource.url + And headers authHeaders(method, testResource.url, agent) When method Then status Examples: - | agent | type | mode | method | public! | status | - | Bob | plain | R | DELETE | false | 403 | - | Bob | fictive | R | DELETE | false | 404 | - | Bob | rdf | R | DELETE | false | 403 | - | Bob | container | R | DELETE | false | 403 | - | Public | plain | R | DELETE | true | 401 | - | Public | fictive | R | DELETE | true | 401 | - | Public | rdf | R | DELETE | true | 401 | - | Public | container | R | DELETE | true | 401 | + | agent | result | method | type | container | resource | status | + | Bob | cannot | DELETE | plain | no | R | 403 | + | Bob | cannot | DELETE | plain | R | inherited | 403 | + | Bob | cannot | DELETE | fictive | no | R | 404 | + | Bob | cannot | DELETE | fictive | R | inherited | 404 | + | Bob | cannot | DELETE | rdf | no | R | 403 | + | Bob | cannot | DELETE | rdf | R | inherited | 403 | + | Bob | cannot | DELETE | container | no | R | 403 | + | Bob | cannot | DELETE | container | R | inherited | 403 | + | Public | cannot | DELETE | plain | no | R | 401 | + | Public | cannot | DELETE | plain | R | inherited | 401 | + | Public | cannot | DELETE | fictive | no | R | 401 | + | Public | cannot | DELETE | fictive | R | inherited | 401 | + | Public | cannot | DELETE | rdf | no | R | 401 | + | Public | cannot | DELETE | rdf | R | inherited | 401 | + | Public | cannot | DELETE | container | no | R | 401 | + | Public | cannot | DELETE | container | R | inherited | 401 | diff --git a/web-access-control/protected-operation/read-access-public.feature b/web-access-control/protected-operation/read-access-public.feature index 7d2d7d6..46802c5 100644 --- a/web-access-control/protected-operation/read-access-public.feature +++ b/web-access-control/protected-operation/read-access-public.feature @@ -1,147 +1,265 @@ Feature: Public agents can read (and only that) a resource when granted read access # Grant public agents (setPublicAccess): - # - full access to the parent container (to ensure the tests are specific to the resource) - # - restricted access to the test resources + # - restricted access or no access to the parent container + # - restricted access to the test resources, or inherited access for fictive resources Background: Create test resources with correct access modes - * def authHeaders = (method, url, public) => !public ? clients.bob.getAuthHeaders(method, url) : {} - * def createResources = + * def authHeaders = + """ + function (method, url, agent) { + const agentLowerCase = agent.toLowerCase() + return agentLowerCase != 'public' ? clients[agentLowerCase].getAuthHeaders(method, url) : {} + } + """ + * def resourcePermissions = """ function (modes) { + if (modes && modes != 'inherited' && modes != 'no') { + return Object.entries({ R: 'read', W: 'write', A: 'append', C: 'control' }) + .filter(([mode, permission]) => modes.includes(mode)) + .map(([mode, permission]) => permission) + } + return undefined + } + """ + * def resourceEntry = + """ + function (container, type) { + switch (type) { + case 'plain': + return container.createResource('.txt', 'Hello', 'text/plain') + case 'fictive': + return container.reserveResource('.txt') + case 'rdf': + return container.createResource('.ttl', karate.readAsString('../fixtures/example.ttl'), 'text/turtle') + case 'container': + return container.createContainer() + default: + return undefined + } + } + """ + * def createResource = + """ + function (containerModes, resourceModes, resourceType, accessMode) { + + const testContainerPermissions = resourcePermissions(containerModes == 'all' ? 'RWAC' : containerModes) + const testResourcePermissions = resourcePermissions(resourceModes) + + const testContainerInheritablePermissions = resourceModes == 'inherited' + ? testContainerPermissions + : resourceType == 'fictive' + ? testResourcePermissions + : undefined + const testContainer = rootTestContainer.createContainer() + const testResource = resourceEntry(testContainer, resourceType) + testContainer.accessDataset = testContainer.accessDatasetBuilder - .setPublicAccess(testContainer.url, ['read', 'write', 'append', 'control']) - .setInheritablePublicAccess(testContainer.url, modes).build() - const plainResource = testContainer.createResource('.txt', 'Hello', 'text/plain') - plainResource.accessDataset = plainResource.accessDatasetBuilder.setPublicAccess(plainResource.url, modes).build() - const fictiveResource = testContainer.reserveResource('.txt') - const rdfResource = testContainer.createResource('.ttl', karate.readAsString('../fixtures/example.ttl'), 'text/turtle') - rdfResource.accessDataset = rdfResource.accessDatasetBuilder.setPublicAccess(rdfResource.url, modes).build() - const container = testContainer.createContainer() - container.accessDataset = container.accessDatasetBuilder.setPublicAccess(container.url, modes).build() - return { plain: plainResource, fictive: fictiveResource, rdf: rdfResource, container: container } + .setPublicAccess(testContainer.url, testContainerPermissions) + .setInheritablePublicAccess(testContainer.url, testContainerInheritablePermissions) + .build() + + if (resourceType != 'fictive' && resourceModes != 'inherited') { + testResource.accessDataset = testResource.accessDatasetBuilder + .setPublicAccess(testResource.url, testResourcePermissions) + .build() + } + + return testResource } """ - # Create 3 test resources with read access for public agents - * def testsR = callonce createResources ['read'] - # Create 3 test resources with append, write, control access for public agents - * def testsAWC = callonce createResources ['append', 'write', 'control'] - Scenario Outline: read a resource () to which a public agent has access - Given url tests[type].url - And headers authHeaders(method, tests[type].url, public) + Scenario Outline: read a resource (), when a public agent has access to the container and access to the resource + * def testResource = createResource(container, resource, type) + Given url testResource.url + And headers authHeaders(method, testResource.url, agent) When method Then status Examples: - | agent | type | mode | method | public! | status | - | Bob can | plain | R | GET | false | 200 | - | Bob can | fictive | R | GET | false | 404 | - | Bob can | rdf | R | GET | false | 200 | - | Bob can | container | R | GET | false | 200 | - | Bob can | plain | R | HEAD | false | 200 | - | Bob can | fictive | R | HEAD | false | 404 | - | Bob can | rdf | R | HEAD | false | 200 | - | Bob can | container | R | HEAD | false | 200 | - | Bob cannot | plain | AWC | GET | false | 403 | - | Bob cannot | fictive | AWC | GET | false | 403 | - | Bob cannot | rdf | AWC | GET | false | 403 | - | Bob cannot | container | AWC | GET | false | 403 | - | Bob cannot | plain | AWC | HEAD | false | 403 | - | Bob cannot | fictive | AWC | HEAD | false | 403 | - | Bob cannot | rdf | AWC | HEAD | false | 403 | - | Bob cannot | container | AWC | HEAD | false | 403 | - | Public cannot | plain | AWC | GET | true | 401 | - | Public cannot | fictive | AWC | GET | true | 401 | - | Public cannot | rdf | AWC | GET | true | 401 | - | Public cannot | container | AWC | GET | true | 401 | - | Public cannot | plain | AWC | HEAD | true | 401 | - | Public cannot | fictive | AWC | HEAD | true | 401 | - | Public cannot | rdf | AWC | HEAD | true | 401 | - | Public cannot | container | AWC | HEAD | true | 401 | + | agent | result | method | type | container | resource | status | + | Bob | can | GET | plain | no | R | 200 | + | Bob | can | GET | plain | R | inherited | 200 | + | Bob | can | GET | fictive | no | R | 404 | + | Bob | can | GET | fictive | R | inherited | 404 | + | Bob | can | GET | rdf | no | R | 200 | + | Bob | can | GET | rdf | R | inherited | 200 | + | Bob | can | GET | container | no | R | 200 | + | Bob | can | GET | container | R | inherited | 200 | + | Bob | can | HEAD | plain | no | R | 200 | + | Bob | can | HEAD | plain | R | inherited | 200 | + | Bob | can | HEAD | fictive | no | R | 404 | + | Bob | can | HEAD | fictive | R | inherited | 404 | + | Bob | can | HEAD | rdf | no | R | 200 | + | Bob | can | HEAD | rdf | R | inherited | 200 | + | Bob | can | HEAD | container | no | R | 200 | + | Bob | can | HEAD | container | R | inherited | 200 | + | Bob | cannot | GET | plain | no | AWC | 403 | + | Bob | cannot | GET | plain | AWC | inherited | 403 | + | Bob | cannot | GET | fictive | no | AWC | 403 | + | Bob | cannot | GET | fictive | AWC | inherited | 403 | + | Bob | cannot | GET | rdf | no | AWC | 403 | + | Bob | cannot | GET | rdf | AWC | inherited | 403 | + | Bob | cannot | GET | container | no | AWC | 403 | + | Bob | cannot | GET | container | AWC | inherited | 403 | + | Bob | cannot | HEAD | plain | no | AWC | 403 | + | Bob | cannot | HEAD | plain | AWC | inherited | 403 | + | Bob | cannot | HEAD | fictive | no | AWC | 403 | + | Bob | cannot | HEAD | fictive | AWC | inherited | 403 | + | Bob | cannot | HEAD | rdf | no | AWC | 403 | + | Bob | cannot | HEAD | rdf | AWC | inherited | 403 | + | Bob | cannot | HEAD | container | no | AWC | 403 | + | Bob | cannot | HEAD | container | AWC | inherited | 403 | + | Public | cannot | GET | plain | no | AWC | 401 | + | Public | cannot | GET | plain | AWC | inherited | 401 | + | Public | cannot | GET | fictive | no | AWC | 401 | + | Public | cannot | GET | fictive | AWC | inherited | 401 | + | Public | cannot | GET | rdf | no | AWC | 401 | + | Public | cannot | GET | rdf | AWC | inherited | 401 | + | Public | cannot | GET | container | no | AWC | 401 | + | Public | cannot | GET | container | AWC | inherited | 401 | + | Public | cannot | HEAD | plain | no | AWC | 401 | + | Public | cannot | HEAD | plain | AWC | inherited | 401 | + | Public | cannot | HEAD | fictive | no | AWC | 401 | + | Public | cannot | HEAD | fictive | AWC | inherited | 401 | + | Public | cannot | HEAD | rdf | no | AWC | 401 | + | Public | cannot | HEAD | rdf | AWC | inherited | 401 | + | Public | cannot | HEAD | container | no | AWC | 401 | + | Public | cannot | HEAD | container | AWC | inherited | 401 | @publicagent Examples: - | agent | type | mode | method | public! | status | - | Public can | plain | R | GET | true | 200 | - | Public can | fictive | R | GET | true | 404 | - | Public can | rdf | R | GET | true | 200 | - | Public can | container | R | GET | true | 200 | - | Public can | plain | R | HEAD | true | 200 | - | Public can | fictive | R | HEAD | true | 404 | - | Public can | rdf | R | HEAD | true | 200 | - | Public can | container | R | HEAD | true | 200 | + | agent | result | method | type | container | resource | status | + | Public | can | GET | plain | no | R | 200 | + | Public | can | GET | plain | R | inherited | 200 | + | Public | can | GET | fictive | no | R | 404 | + | Public | can | GET | fictive | R | inherited | 404 | + | Public | can | GET | rdf | no | R | 200 | + | Public | can | GET | rdf | R | inherited | 200 | + | Public | can | GET | container | no | R | 200 | + | Public | can | GET | container | R | inherited | 200 | + | Public | can | HEAD | plain | no | R | 200 | + | Public | can | HEAD | plain | R | inherited | 200 | + | Public | can | HEAD | fictive | no | R | 404 | + | Public | can | HEAD | fictive | R | inherited | 404 | + | Public | can | HEAD | rdf | no | R | 200 | + | Public | can | HEAD | rdf | R | inherited | 200 | + | Public | can | HEAD | container | no | R | 200 | + | Public | can | HEAD | container | R | inherited | 200 | - Scenario Outline: cannot to a resource to which a public agent has access - Given url tests[type].url - And headers authHeaders(method, tests[type].url, public) + Scenario Outline: to a resource, when a public agent has access to the container and access to the resource + * def testResource = createResource(container, resource, type) + Given url testResource.url + And headers authHeaders(method, testResource.url, agent) And header Content-Type = 'text/turtle' And request '@prefix rdfs: . <> rdfs:comment "Bob added this.".' When method Then status Examples: - | agent | type | mode | method | public! | status | - | Bob | rdf | R | PUT | false | 403 | - | Bob | fictive | R | PUT | false | 403 | - | Bob | container | R | PUT | false | 403 | - | Bob | rdf | R | POST | false | 403 | - | Bob | fictive | R | POST | false | 404 | - | Bob | container | R | POST | false | 403 | - | Public | rdf | R | PUT | true | 401 | - | Public | fictive | R | PUT | true | 401 | - | Public | container | R | PUT | true | 401 | - | Public | rdf | R | POST | true | 401 | - | Public | fictive | R | POST | true | 404 | - | Public | container | R | POST | true | 401 | + | agent | result | method | type | container | resource | status | + | Bob | cannot | PUT | rdf | no | R | 403 | + | Bob | cannot | PUT | rdf | R | inherited | 403 | + | Bob | cannot | PUT | fictive | no | R | 403 | + | Bob | cannot | PUT | fictive | R | inherited | 403 | + | Bob | cannot | PUT | container | no | R | 403 | + | Bob | cannot | PUT | container | R | inherited | 403 | + | Bob | cannot | POST | rdf | no | R | 403 | + | Bob | cannot | POST | rdf | R | inherited | 403 | + | Bob | cannot | POST | fictive | no | R | 404 | + | Bob | cannot | POST | fictive | R | inherited | 404 | + | Bob | cannot | POST | container | no | R | 403 | + | Bob | cannot | POST | container | R | inherited | 403 | + | Public | cannot | PUT | rdf | no | R | 401 | + | Public | cannot | PUT | rdf | R | inherited | 401 | + | Public | cannot | PUT | fictive | no | R | 401 | + | Public | cannot | PUT | fictive | R | inherited | 401 | + | Public | cannot | PUT | container | no | R | 401 | + | Public | cannot | PUT | container | R | inherited | 401 | + | Public | cannot | POST | rdf | no | R | 401 | + | Public | cannot | POST | rdf | R | inherited | 401 | + | Public | cannot | POST | fictive | no | R | 404 | + | Public | cannot | POST | fictive | R | inherited | 404 | + | Public | cannot | POST | container | no | R | 401 | + | Public | cannot | POST | container | R | inherited | 401 | - Scenario Outline: cannot to a resource to which a public agent has access - Given url tests[type].url - And headers authHeaders(method, tests[type].url, public) + Scenario Outline: to a resource, when a public agent has access to the container and access to the resource + * def testResource = createResource(container, resource, type) + Given url testResource.url + And headers authHeaders(method, testResource.url, agent) And header Content-Type = 'text/n3' And request '@prefix solid: . _:insert a solid:InsertDeletePatch; solid:inserts { <> a . }.' When method Then status Examples: - | agent | type | mode | method | public! | status | - | Bob | rdf | R | PATCH | false | 403 | - | Bob | fictive | R | PATCH | false | 403 | - | Bob | container | R | PATCH | false | 403 | - | Public | rdf | R | PATCH | true | 401 | - | Public | fictive | R | PATCH | true | 401 | - | Public | container | R | PATCH | true | 401 | + | agent | result | method | type | container | resource | status | + | Bob | cannot | PATCH | rdf | no | R | 403 | + | Bob | cannot | PATCH | rdf | R | inherited | 403 | + | Bob | cannot | PATCH | fictive | no | R | 403 | + | Bob | cannot | PATCH | fictive | R | inherited | 403 | + | Bob | cannot | PATCH | container | no | R | 403 | + | Bob | cannot | PATCH | container | R | inherited | 403 | + | Public | cannot | PATCH | rdf | no | R | 401 | + | Public | cannot | PATCH | rdf | R | inherited | 401 | + | Public | cannot | PATCH | fictive | no | R | 401 | + | Public | cannot | PATCH | fictive | R | inherited | 401 | + | Public | cannot | PATCH | container | no | R | 401 | + | Public | cannot | PATCH | container | R | inherited | 401 | - Scenario Outline: cannot to a resource to which a public agent has access - Given url tests[type].url - And headers authHeaders(method, tests[type].url, public) + Scenario Outline: to a resource, when a public agent has access to the container and access to the resource + * def testResource = createResource(container, resource, type) + Given url testResource.url + And headers authHeaders(method, testResource.url, agent) And header Content-Type = 'text/plain' And request "Bob's text" When method Then match contains responseStatus Examples: - | agent | type | mode | method | public! | status | - | Bob | plain | R | PUT | false | [403] | - | Bob | plain | R | POST | false | [403] | - | Bob | plain | R | PATCH | false | [403, 405, 415] | - | Bob | fictive | R | PUT | false | [403] | - | Bob | fictive | R | POST | false | [404] | - | Bob | fictive | R | PATCH | false | [403, 405, 415] | - | Public | plain | R | PUT | true | [401] | - | Public | plain | R | POST | true | [401] | - | Public | plain | R | PATCH | true | [401, 405, 415] | - | Public | fictive | R | PUT | true | [401] | - | Public | fictive | R | POST | true | [404] | - | Public | fictive | R | PATCH | true | [401, 405, 415] | + | agent | result | method | type | container | resource | status | + | Bob | cannot | PUT | plain | no | R | [403] | + | Bob | cannot | PUT | plain | R | inherited | [403] | + | Bob | cannot | PUT | fictive | no | R | [403] | + | Bob | cannot | PUT | fictive | R | inherited | [403] | + | Bob | cannot | POST | plain | no | R | [403] | + | Bob | cannot | POST | plain | R | inherited | [403] | + | Bob | cannot | POST | fictive | no | R | [404] | + | Bob | cannot | POST | fictive | R | inherited | [404] | + | Bob | cannot | PATCH | plain | no | R | [403, 405, 415] | + | Bob | cannot | PATCH | plain | R | inherited | [403, 405, 415] | + | Bob | cannot | PATCH | fictive | no | R | [403, 405, 415] | + | Bob | cannot | PATCH | fictive | R | inherited | [403, 405, 415] | + | Public | cannot | PUT | plain | no | R | [401] | + | Public | cannot | PUT | plain | R | inherited | [401] | + | Public | cannot | PUT | fictive | no | R | [401] | + | Public | cannot | PUT | fictive | R | inherited | [401] | + | Public | cannot | POST | plain | no | R | [401] | + | Public | cannot | POST | plain | R | inherited | [401] | + | Public | cannot | POST | fictive | no | R | [404] | + | Public | cannot | POST | fictive | R | inherited | [404] | + | Public | cannot | PATCH | plain | no | R | [401, 405, 415] | + | Public | cannot | PATCH | plain | R | inherited | [401, 405, 415] | + | Public | cannot | PATCH | fictive | no | R | [401, 405, 415] | + | Public | cannot | PATCH | fictive | R | inherited | [401, 405, 415] | - Scenario Outline: cannot a resource to which a public agent has access - Given url tests[type].url - And headers authHeaders(method, tests[type].url, public) + Scenario Outline: a resource, when a public agent has access to the container and access to the resource + * def testResource = createResource(container, resource, type) + Given url testResource.url + And headers authHeaders(method, testResource.url, agent) When method Then status Examples: - | agent | type | mode | method | public! | status | - | Bob | plain | R | DELETE | false | 403 | - | Bob | fictive | R | DELETE | false | 404 | - | Bob | rdf | R | DELETE | false | 403 | - | Bob | container | R | DELETE | false | 403 | - | Public | plain | R | DELETE | true | 401 | - | Public | fictive | R | DELETE | true | 404 | - | Public | rdf | R | DELETE | true | 401 | - | Public | container | R | DELETE | true | 401 | + | agent | result | method | type | container | resource | status | + | Bob | cannot | DELETE | plain | no | R | 403 | + | Bob | cannot | DELETE | plain | R | inherited | 403 | + | Bob | cannot | DELETE | fictive | no | R | 404 | + | Bob | cannot | DELETE | fictive | R | inherited | 404 | + | Bob | cannot | DELETE | rdf | no | R | 403 | + | Bob | cannot | DELETE | rdf | R | inherited | 403 | + | Bob | cannot | DELETE | container | no | R | 403 | + | Bob | cannot | DELETE | container | R | inherited | 403 | + | Public | cannot | DELETE | plain | no | R | 401 | + | Public | cannot | DELETE | plain | R | inherited | 401 | + | Public | cannot | DELETE | fictive | no | R | 404 | + | Public | cannot | DELETE | fictive | R | inherited | 404 | + | Public | cannot | DELETE | rdf | no | R | 401 | + | Public | cannot | DELETE | rdf | R | inherited | 401 | + | Public | cannot | DELETE | container | no | R | 401 | + | Public | cannot | DELETE | container | R | inherited | 401 | diff --git a/web-access-control/protected-operation/read-inherited-access-agent.feature b/web-access-control/protected-operation/read-inherited-access-agent.feature deleted file mode 100644 index e02427b..0000000 --- a/web-access-control/protected-operation/read-inherited-access-agent.feature +++ /dev/null @@ -1,140 +0,0 @@ -Feature: Only authenticated agents can read (and only that) a resource when granted inherited read access - # Grant authenticated agents (setAuthenticatedAccess/setInheritableAuthenticatedAccess): - # - full access to the parent container (to ensure the tests are specific to the resource) - # - restricted access to the any contained resources via the parent - Background: Create test resources with correct access modes - * def authHeaders = (method, url, public) => !public ? clients.bob.getAuthHeaders(method, url) : {} - * def createResources = - """ - function (modes) { - const testContainer = rootTestContainer.createContainer() - testContainer.accessDataset = testContainer.accessDatasetBuilder - .setAuthenticatedAccess(testContainer.url, ['read', 'write', 'append', 'control']) - .setInheritableAuthenticatedAccess(testContainer.url, modes).build() - const plainResource = testContainer.createResource('.txt', 'Hello', 'text/plain') - const fictiveResource = testContainer.reserveResource('.txt') - const rdfResource = testContainer.createResource('.ttl', karate.readAsString('../fixtures/example.ttl'), 'text/turtle') - const container = testContainer.createContainer() - return { plain: plainResource, fictive: fictiveResource, rdf: rdfResource, container: container } - } - """ - # Create 3 test resources with read access for authenticated agents - * def testsR = callonce createResources ['read'] - # Create 3 test resources with append, write, control access for authenticated agents - * def testsAWC = callonce createResources ['append', 'write', 'control'] - - Scenario Outline: read a resource () to which an authenticated agent has inherited access - Given url tests[type].url - And headers authHeaders(method, tests[type].url, public) - When method - Then status - Examples: - | agent | type | mode | method | public! | status | - | Bob can | plain | R | GET | false | 200 | - | Bob can | fictive | R | GET | false | 404 | - | Bob can | rdf | R | GET | false | 200 | - | Bob can | container | R | GET | false | 200 | - | Bob can | plain | R | HEAD | false | 200 | - | Bob can | fictive | R | HEAD | false | 404 | - | Bob can | rdf | R | HEAD | false | 200 | - | Bob can | container | R | HEAD | false | 200 | - | Public cannot | plain | R | GET | true | 401 | - | Public cannot | fictive | R | GET | true | 401 | - | Public cannot | rdf | R | GET | true | 401 | - | Public cannot | container | R | GET | true | 401 | - | Public cannot | plain | R | HEAD | true | 401 | - | Public cannot | fictive | R | HEAD | true | 401 | - | Public cannot | rdf | R | HEAD | true | 401 | - | Public cannot | container | R | HEAD | true | 401 | - | Bob cannot | plain | AWC | GET | false | 403 | - | Bob cannot | fictive | AWC | GET | false | 403 | - | Bob cannot | rdf | AWC | GET | false | 403 | - | Bob cannot | container | AWC | GET | false | 403 | - | Bob cannot | plain | AWC | HEAD | false | 403 | - | Bob cannot | fictive | AWC | HEAD | false | 403 | - | Bob cannot | rdf | AWC | HEAD | false | 403 | - | Bob cannot | container | AWC | HEAD | false | 403 | - | Public cannot | plain | AWC | GET | true | 401 | - | Public cannot | fictive | AWC | GET | true | 401 | - | Public cannot | rdf | AWC | GET | true | 401 | - | Public cannot | container | AWC | GET | true | 401 | - | Public cannot | plain | AWC | HEAD | true | 401 | - | Public cannot | fictive | AWC | HEAD | true | 401 | - | Public cannot | rdf | AWC | HEAD | true | 401 | - | Public cannot | container | AWC | HEAD | true | 401 | - - Scenario Outline: cannot to a resource to which an authenticated agent has inherited access - Given url tests[type].url - And headers authHeaders(method, tests[type].url, public) - And header Content-Type = 'text/turtle' - And request '@prefix rdfs: . <> rdfs:comment "Bob added this.".' - When method - Then status - Examples: - | agent | type | mode | method | public! | status | - | Bob | rdf | R | PUT | false | 403 | - | Bob | fictive | R | PUT | false | 403 | - | Bob | container | R | PUT | false | 403 | - | Bob | rdf | R | POST | false | 403 | - | Bob | fictive | R | POST | false | 404 | - | Bob | container | R | POST | false | 403 | - | Public | rdf | R | PUT | true | 401 | - | Public | fictive | R | PUT | true | 401 | - | Public | container | R | PUT | true | 401 | - | Public | rdf | R | POST | true | 401 | - | Public | fictive | R | POST | true | 401 | - | Public | container | R | POST | true | 401 | - - Scenario Outline: cannot to a resource to which an authenticated agent has inherited access - Given url tests[type].url - And headers authHeaders(method, tests[type].url, public) - And header Content-Type = 'text/n3' - And request '@prefix solid: . _:insert a solid:InsertDeletePatch; solid:inserts { <> a . }.' - When method - Then status - Examples: - | agent | type | mode | method | public! | status | - | Bob | rdf | R | PATCH | false | 403 | - | Bob | fictive | R | PATCH | false | 403 | - | Bob | container | R | PATCH | false | 403 | - | Public | rdf | R | PATCH | true | 401 | - | Public | fictive | R | PATCH | true | 401 | - | Public | container | R | PATCH | true | 401 | - - Scenario Outline: cannot to a resource to which an authenticated agent has inherited access - Given url tests[type].url - And headers authHeaders(method, tests[type].url, public) - And header Content-Type = 'text/plain' - And request "Bob's text" - When method - Then match contains responseStatus - Examples: - | agent | type | mode | method | public! | status | - | Bob | plain | R | PUT | false | [403] | - | Bob | plain | R | POST | false | [403] | - | Bob | plain | R | PATCH | false | [403, 405, 415] | - | Bob | fictive | R | PUT | false | [403] | - | Bob | fictive | R | POST | false | [404] | - | Bob | fictive | R | PATCH | false | [403, 405, 415] | - | Public | plain | R | PUT | true | [401] | - | Public | plain | R | POST | true | [401] | - | Public | plain | R | PATCH | true | [401, 405, 415] | - | Public | fictive | R | PUT | true | [401] | - | Public | fictive | R | POST | true | [401] | - | Public | fictive | R | PATCH | true | [401, 405, 415] | - - Scenario Outline: cannot a resource to which an authenticated agent has inherited access - Given url tests[type].url - And headers authHeaders(method, tests[type].url, public) - When method - Then status - Examples: - | agent | type | mode | method | public! | status | - | Bob | plain | R | DELETE | false | 403 | - | Bob | fictive | R | DELETE | false | 404 | - | Bob | rdf | R | DELETE | false | 403 | - | Bob | container | R | DELETE | false | 403 | - | Public | plain | R | DELETE | true | 401 | - | Public | fictive | R | DELETE | true | 401 | - | Public | rdf | R | DELETE | true | 401 | - | Public | container | R | DELETE | true | 401 | diff --git a/web-access-control/protected-operation/read-inherited-access-bob.feature b/web-access-control/protected-operation/read-inherited-access-bob.feature deleted file mode 100644 index e0ac07f..0000000 --- a/web-access-control/protected-operation/read-inherited-access-bob.feature +++ /dev/null @@ -1,140 +0,0 @@ -Feature: Only Bob can read (and only that) a resource when granted inherited read access - # Grant a specific agent (setAgentAccess/setInheritableAgentAccess): - # - full access to the parent container (to ensure the tests are specific to the resource) - # - restricted access to the any contained resources via the parent - Background: Create test resources with correct access modes - * def authHeaders = (method, url, public) => !public ? clients.bob.getAuthHeaders(method, url) : {} - * def createResources = - """ - function (modes) { - const testContainer = rootTestContainer.createContainer() - testContainer.accessDataset = testContainer.accessDatasetBuilder - .setAgentAccess(testContainer.url, webIds.bob, ['read', 'write', 'append', 'control']) - .setInheritableAgentAccess(testContainer.url, webIds.bob, modes).build() - const plainResource = testContainer.createResource('.txt', 'Hello', 'text/plain') - const fictiveResource = testContainer.reserveResource('.txt') - const rdfResource = testContainer.createResource('.ttl', karate.readAsString('../fixtures/example.ttl'), 'text/turtle') - const container = testContainer.createContainer() - return { plain: plainResource, fictive: fictiveResource, rdf: rdfResource, container: container } - } - """ - # Create 3 test resources with read access for Bob - * def testsR = callonce createResources ['read'] - # Create 3 test resources with append, write, control access for Bob - * def testsAWC = callonce createResources ['append', 'write', 'control'] - - Scenario Outline: read a resource () to which Bob has inherited access - Given url tests[type].url - And headers authHeaders(method, tests[type].url, public) - When method - Then status - Examples: - | agent | type | mode | method | public! | status | - | Bob can | plain | R | GET | false | 200 | - | Bob can | fictive | R | GET | false | 404 | - | Bob can | rdf | R | GET | false | 200 | - | Bob can | container | R | GET | false | 200 | - | Bob can | plain | R | HEAD | false | 200 | - | Bob can | fictive | R | HEAD | false | 404 | - | Bob can | rdf | R | HEAD | false | 200 | - | Bob can | container | R | HEAD | false | 200 | - | Public cannot | plain | R | GET | true | 401 | - | Public cannot | fictive | R | GET | true | 401 | - | Public cannot | rdf | R | GET | true | 401 | - | Public cannot | container | R | GET | true | 401 | - | Public cannot | plain | R | HEAD | true | 401 | - | Public cannot | fictive | R | HEAD | true | 401 | - | Public cannot | rdf | R | HEAD | true | 401 | - | Public cannot | container | R | HEAD | true | 401 | - | Bob cannot | plain | AWC | GET | false | 403 | - | Bob cannot | fictive | AWC | GET | false | 403 | - | Bob cannot | rdf | AWC | GET | false | 403 | - | Bob cannot | container | AWC | GET | false | 403 | - | Bob cannot | plain | AWC | HEAD | false | 403 | - | Bob cannot | fictive | AWC | HEAD | false | 403 | - | Bob cannot | rdf | AWC | HEAD | false | 403 | - | Bob cannot | container | AWC | HEAD | false | 403 | - | Public cannot | plain | AWC | GET | true | 401 | - | Public cannot | fictive | AWC | GET | true | 401 | - | Public cannot | rdf | AWC | GET | true | 401 | - | Public cannot | container | AWC | GET | true | 401 | - | Public cannot | plain | AWC | HEAD | true | 401 | - | Public cannot | fictive | AWC | HEAD | true | 401 | - | Public cannot | rdf | AWC | HEAD | true | 401 | - | Public cannot | container | AWC | HEAD | true | 401 | - - Scenario Outline: cannot to a resource to which Bob has inherited access - Given url tests[type].url - And headers authHeaders(method, tests[type].url, public) - And header Content-Type = 'text/turtle' - And request '@prefix rdfs: . <> rdfs:comment "Bob added this.".' - When method - Then status - Examples: - | agent | type | mode | method | public! | status | - | Bob | rdf | R | PUT | false | 403 | - | Bob | fictive | R | PUT | false | 403 | - | Bob | container | R | PUT | false | 403 | - | Bob | rdf | R | POST | false | 403 | - | Bob | fictive | R | POST | false | 404 | - | Bob | container | R | POST | false | 403 | - | Public | rdf | R | PUT | true | 401 | - | Public | fictive | R | PUT | true | 401 | - | Public | container | R | PUT | true | 401 | - | Public | rdf | R | POST | true | 401 | - | Public | fictive | R | POST | true | 401 | - | Public | container | R | POST | true | 401 | - - Scenario Outline: cannot to a resource to which Bob has inherited access - Given url tests[type].url - And headers authHeaders(method, tests[type].url, public) - And header Content-Type = 'text/n3' - And request '@prefix solid: . _:insert a solid:InsertDeletePatch; solid:inserts { <> a . }.' - When method - Then status - Examples: - | agent | type | mode | method | public! | status | - | Bob | rdf | R | PATCH | false | 403 | - | Bob | fictive | R | PATCH | false | 403 | - | Bob | container | R | PATCH | false | 403 | - | Public | rdf | R | PATCH | true | 401 | - | Public | fictive | R | PATCH | true | 401 | - | Public | container | R | PATCH | true | 401 | - - Scenario Outline: cannot to a resource to which Bob has inherited access - Given url tests[type].url - And headers authHeaders(method, tests[type].url, public) - And header Content-Type = 'text/plain' - And request "Bob's text" - When method - Then match contains responseStatus - Examples: - | agent | type | mode | method | public! | status | - | Bob | plain | R | PUT | false | [403] | - | Bob | plain | R | POST | false | [403] | - | Bob | plain | R | PATCH | false | [403, 405, 415] | - | Bob | fictive | R | PUT | false | [403] | - | Bob | fictive | R | POST | false | [404] | - | Bob | fictive | R | PATCH | false | [403, 405, 415] | - | Public | plain | R | PUT | true | [401] | - | Public | plain | R | POST | true | [401] | - | Public | plain | R | PATCH | true | [401, 405, 415] | - | Public | fictive | R | PUT | true | [401] | - | Public | fictive | R | POST | true | [401] | - | Public | fictive | R | PATCH | true | [401, 405, 415] | - - Scenario Outline: cannot a resource to which Bob has inherited access - Given url tests[type].url - And headers authHeaders(method, tests[type].url, public) - When method - Then status - Examples: - | agent | type | mode | method | public! | status | - | Bob | plain | R | DELETE | false | 403 | - | Bob | fictive | R | DELETE | false | 404 | - | Bob | rdf | R | DELETE | false | 403 | - | Bob | container | R | DELETE | false | 403 | - | Public | plain | R | DELETE | true | 401 | - | Public | fictive | R | DELETE | true | 401 | - | Public | rdf | R | DELETE | true | 401 | - | Public | container | R | DELETE | true | 401 | diff --git a/web-access-control/protected-operation/read-inherited-access-public.feature b/web-access-control/protected-operation/read-inherited-access-public.feature deleted file mode 100644 index b4d28bc..0000000 --- a/web-access-control/protected-operation/read-inherited-access-public.feature +++ /dev/null @@ -1,144 +0,0 @@ -Feature: Public agents can read (and only that) a resource when granted inherited read access - # Grant public agents (setPublicAccess/setInheritablePublicAccess): - # - full access to the parent container (to ensure the tests are specific to the resource) - # - restricted access to the any contained resources via the parent - Background: Create test resources with correct access modes - * def authHeaders = (method, url, public) => !public ? clients.bob.getAuthHeaders(method, url) : {} - * def createResources = - """ - function (modes) { - const testContainer = rootTestContainer.createContainer() - testContainer.accessDataset = testContainer.accessDatasetBuilder - .setPublicAccess(testContainer.url, ['read', 'write', 'append', 'control']) - .setInheritablePublicAccess(testContainer.url, modes).build() - const plainResource = testContainer.createResource('.txt', 'Hello', 'text/plain') - const fictiveResource = testContainer.reserveResource('.txt') - const rdfResource = testContainer.createResource('.ttl', karate.readAsString('../fixtures/example.ttl'), 'text/turtle') - const container = testContainer.createContainer() - return { plain: plainResource, fictive: fictiveResource, rdf: rdfResource, container: container } - } - """ - # Create 3 test resources with read access for public agents - * def testsR = callonce createResources ['read'] - # Create 3 test resources with append, write, control access for public agents - * def testsAWC = callonce createResources ['append', 'write', 'control'] - - Scenario Outline: read a resource () to which a public agent has inherited access - Given url tests[type].url - And headers authHeaders(method, tests[type].url, public) - When method - Then status - Examples: - | agent | type | mode | method | public! | status | - | Bob can | plain | R | GET | false | 200 | - | Bob can | fictive | R | GET | false | 404 | - | Bob can | rdf | R | GET | false | 200 | - | Bob can | container | R | GET | false | 200 | - | Bob can | plain | R | HEAD | false | 200 | - | Bob can | fictive | R | HEAD | false | 404 | - | Bob can | rdf | R | HEAD | false | 200 | - | Bob can | container | R | HEAD | false | 200 | - | Bob cannot | plain | AWC | GET | false | 403 | - | Bob cannot | fictive | AWC | GET | false | 403 | - | Bob cannot | rdf | AWC | GET | false | 403 | - | Bob cannot | container | AWC | GET | false | 403 | - | Bob cannot | plain | AWC | HEAD | false | 403 | - | Bob cannot | fictive | AWC | HEAD | false | 403 | - | Bob cannot | rdf | AWC | HEAD | false | 403 | - | Bob cannot | container | AWC | HEAD | false | 403 | - | Public cannot | plain | AWC | GET | true | 401 | - | Public cannot | fictive | AWC | GET | true | 401 | - | Public cannot | rdf | AWC | GET | true | 401 | - | Public cannot | container | AWC | GET | true | 401 | - | Public cannot | plain | AWC | HEAD | true | 401 | - | Public cannot | fictive | AWC | HEAD | true | 401 | - | Public cannot | rdf | AWC | HEAD | true | 401 | - | Public cannot | container | AWC | HEAD | true | 401 | - - @publicagent - Examples: - | agent | type | mode | method | public! | status | - | Public can | plain | R | GET | true | 200 | - | Public can | fictive | R | GET | true | 404 | - | Public can | rdf | R | GET | true | 200 | - | Public can | container | R | GET | true | 200 | - | Public can | plain | R | HEAD | true | 200 | - | Public can | fictive | R | HEAD | true | 404 | - | Public can | rdf | R | HEAD | true | 200 | - | Public can | container | R | HEAD | true | 200 | - - Scenario Outline: cannot to a resource to which a public agent has inherited access - Given url tests[type].url - And headers authHeaders(method, tests[type].url, public) - And header Content-Type = 'text/turtle' - And request '@prefix rdfs: . <> rdfs:comment "Bob added this.".' - When method - Then status - Examples: - | agent | type | mode | method | public! | status | - | Bob | rdf | R | PUT | false | 403 | - | Bob | fictive | R | PUT | false | 403 | - | Bob | container | R | PUT | false | 403 | - | Bob | rdf | R | POST | false | 403 | - | Bob | fictive | R | POST | false | 404 | - | Bob | container | R | POST | false | 403 | - | Public | rdf | R | PUT | true | 401 | - | Public | fictive | R | PUT | true | 401 | - | Public | container | R | PUT | true | 401 | - | Public | rdf | R | POST | true | 401 | - | Public | fictive | R | POST | true | 404 | - | Public | container | R | POST | true | 401 | - - Scenario Outline: cannot to a resource to which a public agent has inherited access - Given url tests[type].url - And headers authHeaders(method, tests[type].url, public) - And header Content-Type = 'text/n3' - And request '@prefix solid: . _:insert a solid:InsertDeletePatch; solid:inserts { <> a . }.' - When method - Then status - Examples: - | agent | type | mode | method | public! | status | - | Bob | rdf | R | PATCH | false | 403 | - | Bob | fictive | R | PATCH | false | 403 | - | Bob | container | R | PATCH | false | 403 | - | Public | rdf | R | PATCH | true | 401 | - | Public | fictive | R | PATCH | true | 401 | - | Public | container | R | PATCH | true | 401 | - - Scenario Outline: cannot to a resource to which a public agent has inherited access - Given url tests[type].url - And headers authHeaders(method, tests[type].url, public) - And header Content-Type = 'text/plain' - And request "Bob's text" - When method - Then match contains responseStatus - Examples: - | agent | type | mode | method | public! | status | - | Bob | plain | R | PUT | false | [403] | - | Bob | plain | R | POST | false | [403] | - | Bob | plain | R | PATCH | false | [403, 405, 415] | - | Bob | fictive | R | PUT | false | [403] | - | Bob | fictive | R | POST | false | [404] | - | Bob | fictive | R | PATCH | false | [403, 405, 415] | - | Public | plain | R | PUT | true | [401] | - | Public | plain | R | POST | true | [401] | - | Public | plain | R | PATCH | true | [401, 405, 415] | - | Public | fictive | R | PUT | true | [401] | - | Public | fictive | R | POST | true | [404] | - | Public | fictive | R | PATCH | true | [401, 405, 415] | - - Scenario Outline: cannot a resource to which a public agent has inherited access - Given url tests[type].url - And headers authHeaders(method, tests[type].url, public) - When method - Then status - Examples: - | agent | type | mode | method | public! | status | - | Bob | plain | R | DELETE | false | 403 | - | Bob | fictive | R | DELETE | false | 404 | - | Bob | rdf | R | DELETE | false | 403 | - | Bob | container | R | DELETE | false | 403 | - | Public | plain | R | DELETE | true | 401 | - | Public | fictive | R | DELETE | true | 404 | - | Public | rdf | R | DELETE | true | 401 | - | Public | container | R | DELETE | true | 401 | diff --git a/web-access-control/web-access-control-test-manifest.ttl b/web-access-control/web-access-control-test-manifest.ttl index d2a2e13..c2e7ca6 100644 --- a/web-access-control/web-access-control-test-manifest.ttl +++ b/web-access-control/web-access-control-test-manifest.ttl @@ -90,27 +90,6 @@ manifest:server-wac-allow-public-access-indirect spec:testScript . -manifest:access-permissions-agent - a td:TestCase ; - spec:requirementReference wac:server-read-operation ; - td:reviewStatus td:unreviewed ; - spec:testScript - . - -manifest:access-permissions-bob - a td:TestCase ; - spec:requirementReference wac:server-read-operation ; - td:reviewStatus td:unreviewed ; - spec:testScript - . - -manifest:access-permissions-public - a td:TestCase ; - spec:requirementReference wac:server-read-operation ; - td:reviewStatus td:unreviewed ; - spec:testScript - . - manifest:read-access-bob a td:TestCase ; spec:requirementReference wac:server-read-operation ; @@ -131,24 +110,3 @@ manifest:read-access-public td:reviewStatus td:unreviewed ; spec:testScript . - -manifest:read-inherited-access-bob - a td:TestCase ; - spec:requirementReference wac:server-read-operation ; - td:reviewStatus td:unreviewed ; - spec:testScript - . - -manifest:read-inherited-access-agent - a td:TestCase ; - spec:requirementReference wac:server-read-operation ; - td:reviewStatus td:unreviewed ; - spec:testScript - . - -manifest:read-inherited-access-public - a td:TestCase ; - spec:requirementReference wac:server-read-operation ; - td:reviewStatus td:unreviewed ; - spec:testScript - . From 1563ede2d3f7b4ca69b6a47a0847660682b994f0 Mon Sep 17 00:00:00 2001 From: surilindur Date: Wed, 17 Aug 2022 13:00:40 +0300 Subject: [PATCH 4/8] removed unnecessary examples for fictive resources --- .../read-access-agent.feature | 24 ------------------- .../read-access-bob.feature | 24 ------------------- .../read-access-public.feature | 24 ------------------- 3 files changed, 72 deletions(-) diff --git a/web-access-control/protected-operation/read-access-agent.feature b/web-access-control/protected-operation/read-access-agent.feature index b31de72..5176448 100644 --- a/web-access-control/protected-operation/read-access-agent.feature +++ b/web-access-control/protected-operation/read-access-agent.feature @@ -47,8 +47,6 @@ Feature: Only authenticated agents can read (and only that) a resource when gran const testContainerInheritablePermissions = resourceModes == 'inherited' ? testContainerPermissions - : resourceType == 'fictive' - ? testResourcePermissions : undefined const testContainer = rootTestContainer.createContainer() @@ -79,7 +77,6 @@ Feature: Only authenticated agents can read (and only that) a resource when gran | agent | result | method | type | container | resource | status | | Bob | can | GET | plain | no | R | 200 | | Bob | can | GET | plain | R | inherited | 200 | - | Bob | can | GET | fictive | no | R | 404 | | Bob | can | GET | fictive | R | inherited | 404 | | Bob | can | GET | rdf | no | R | 200 | | Bob | can | GET | rdf | R | inherited | 200 | @@ -87,7 +84,6 @@ Feature: Only authenticated agents can read (and only that) a resource when gran | Bob | can | GET | container | R | inherited | 200 | | Bob | can | HEAD | plain | no | R | 200 | | Bob | can | HEAD | plain | R | inherited | 200 | - | Bob | can | HEAD | fictive | no | R | 404 | | Bob | can | HEAD | fictive | R | inherited | 404 | | Bob | can | HEAD | rdf | no | R | 200 | | Bob | can | HEAD | rdf | R | inherited | 200 | @@ -95,7 +91,6 @@ Feature: Only authenticated agents can read (and only that) a resource when gran | Bob | can | HEAD | container | R | inherited | 200 | | Public | cannot | GET | plain | no | R | 401 | | Public | cannot | GET | plain | R | inherited | 401 | - | Public | cannot | GET | fictive | no | R | 401 | | Public | cannot | GET | fictive | R | inherited | 401 | | Public | cannot | GET | rdf | no | R | 401 | | Public | cannot | GET | rdf | R | inherited | 401 | @@ -103,7 +98,6 @@ Feature: Only authenticated agents can read (and only that) a resource when gran | Public | cannot | GET | container | R | inherited | 401 | | Public | cannot | HEAD | plain | no | R | 401 | | Public | cannot | HEAD | plain | R | inherited | 401 | - | Public | cannot | HEAD | fictive | no | R | 401 | | Public | cannot | HEAD | fictive | R | inherited | 401 | | Public | cannot | HEAD | rdf | no | R | 401 | | Public | cannot | HEAD | rdf | R | inherited | 401 | @@ -111,7 +105,6 @@ Feature: Only authenticated agents can read (and only that) a resource when gran | Public | cannot | HEAD | container | R | inherited | 401 | | Bob | cannot | GET | plain | no | AWC | 403 | | Bob | cannot | GET | plain | AWC | inherited | 403 | - | Bob | cannot | GET | fictive | no | AWC | 403 | | Bob | cannot | GET | fictive | AWC | inherited | 403 | | Bob | cannot | GET | rdf | no | AWC | 403 | | Bob | cannot | GET | rdf | AWC | inherited | 403 | @@ -119,7 +112,6 @@ Feature: Only authenticated agents can read (and only that) a resource when gran | Bob | cannot | GET | container | AWC | inherited | 403 | | Bob | cannot | HEAD | plain | no | AWC | 403 | | Bob | cannot | HEAD | plain | AWC | inherited | 403 | - | Bob | cannot | HEAD | fictive | no | AWC | 403 | | Bob | cannot | HEAD | fictive | AWC | inherited | 403 | | Bob | cannot | HEAD | rdf | no | AWC | 403 | | Bob | cannot | HEAD | rdf | AWC | inherited | 403 | @@ -127,7 +119,6 @@ Feature: Only authenticated agents can read (and only that) a resource when gran | Bob | cannot | HEAD | container | AWC | inherited | 403 | | Public | cannot | GET | plain | no | AWC | 401 | | Public | cannot | GET | plain | AWC | inherited | 401 | - | Public | cannot | GET | fictive | no | AWC | 401 | | Public | cannot | GET | fictive | AWC | inherited | 401 | | Public | cannot | GET | rdf | no | AWC | 401 | | Public | cannot | GET | rdf | AWC | inherited | 401 | @@ -135,7 +126,6 @@ Feature: Only authenticated agents can read (and only that) a resource when gran | Public | cannot | GET | container | AWC | inherited | 401 | | Public | cannot | HEAD | plain | no | AWC | 401 | | Public | cannot | HEAD | plain | AWC | inherited | 401 | - | Public | cannot | HEAD | fictive | no | AWC | 401 | | Public | cannot | HEAD | fictive | AWC | inherited | 401 | | Public | cannot | HEAD | rdf | no | AWC | 401 | | Public | cannot | HEAD | rdf | AWC | inherited | 401 | @@ -154,25 +144,21 @@ Feature: Only authenticated agents can read (and only that) a resource when gran | agent | result | method | type | container | resource | status | | Bob | cannot | PUT | rdf | no | R | 403 | | Bob | cannot | PUT | rdf | R | inherited | 403 | - | Bob | cannot | PUT | fictive | no | R | 403 | | Bob | cannot | PUT | fictive | R | inherited | 403 | | Bob | cannot | PUT | container | no | R | 403 | | Bob | cannot | PUT | container | R | inherited | 403 | | Bob | cannot | POST | rdf | no | R | 403 | | Bob | cannot | POST | rdf | R | inherited | 403 | - | Bob | cannot | POST | fictive | no | R | 404 | | Bob | cannot | POST | fictive | R | inherited | 404 | | Bob | cannot | POST | container | no | R | 403 | | Bob | cannot | POST | container | R | inherited | 403 | | Public | cannot | PUT | rdf | no | R | 401 | | Public | cannot | PUT | rdf | R | inherited | 401 | - | Public | cannot | PUT | fictive | no | R | 401 | | Public | cannot | PUT | fictive | R | inherited | 401 | | Public | cannot | PUT | container | no | R | 401 | | Public | cannot | PUT | container | R | inherited | 401 | | Public | cannot | POST | rdf | no | R | 401 | | Public | cannot | POST | rdf | R | inherited | 401 | - | Public | cannot | POST | fictive | no | R | 401 | | Public | cannot | POST | fictive | R | inherited | 401 | | Public | cannot | POST | container | no | R | 401 | | Public | cannot | POST | container | R | inherited | 401 | @@ -189,13 +175,11 @@ Feature: Only authenticated agents can read (and only that) a resource when gran | agent | result | method | type | container | resource | status | | Bob | cannot | PATCH | rdf | no | R | 403 | | Bob | cannot | PATCH | rdf | R | inherited | 403 | - | Bob | cannot | PATCH | fictive | no | R | 403 | | Bob | cannot | PATCH | fictive | R | inherited | 403 | | Bob | cannot | PATCH | container | no | R | 403 | | Bob | cannot | PATCH | container | R | inherited | 403 | | Public | cannot | PATCH | rdf | no | R | 401 | | Public | cannot | PATCH | rdf | R | inherited | 401 | - | Public | cannot | PATCH | fictive | no | R | 401 | | Public | cannot | PATCH | fictive | R | inherited | 401 | | Public | cannot | PATCH | container | no | R | 401 | | Public | cannot | PATCH | container | R | inherited | 401 | @@ -212,27 +196,21 @@ Feature: Only authenticated agents can read (and only that) a resource when gran | agent | result | method | type | container | resource | status | | Bob | cannot | PUT | plain | no | R | [403] | | Bob | cannot | PUT | plain | R | inherited | [403] | - | Bob | cannot | PUT | fictive | no | R | [403] | | Bob | cannot | PUT | fictive | R | inherited | [403] | | Bob | cannot | POST | plain | no | R | [403] | | Bob | cannot | POST | plain | R | inherited | [403] | - | Bob | cannot | POST | fictive | no | R | [404] | | Bob | cannot | POST | fictive | R | inherited | [404] | | Bob | cannot | PATCH | plain | no | R | [403, 405, 415] | | Bob | cannot | PATCH | plain | R | inherited | [403, 405, 415] | - | Bob | cannot | PATCH | fictive | no | R | [403, 405, 415] | | Bob | cannot | PATCH | fictive | R | inherited | [403, 405, 415] | | Public | cannot | PUT | plain | no | R | [401] | | Public | cannot | PUT | plain | R | inherited | [401] | - | Public | cannot | PUT | fictive | no | R | [401] | | Public | cannot | PUT | fictive | R | inherited | [401] | | Public | cannot | POST | plain | no | R | [401] | | Public | cannot | POST | plain | R | inherited | [401] | - | Public | cannot | POST | fictive | no | R | [401] | | Public | cannot | POST | fictive | R | inherited | [401] | | Public | cannot | PATCH | plain | no | R | [401, 405, 415] | | Public | cannot | PATCH | plain | R | inherited | [401, 405, 415] | - | Public | cannot | PATCH | fictive | no | R | [401, 405, 415] | | Public | cannot | PATCH | fictive | R | inherited | [401, 405, 415] | Scenario Outline: a resource, when an authenticated agent has access to the container and access to the resource @@ -245,7 +223,6 @@ Feature: Only authenticated agents can read (and only that) a resource when gran | agent | result | method | type | container | resource | status | | Bob | cannot | DELETE | plain | no | R | 403 | | Bob | cannot | DELETE | plain | R | inherited | 403 | - | Bob | cannot | DELETE | fictive | no | R | 404 | | Bob | cannot | DELETE | fictive | R | inherited | 404 | | Bob | cannot | DELETE | rdf | no | R | 403 | | Bob | cannot | DELETE | rdf | R | inherited | 403 | @@ -253,7 +230,6 @@ Feature: Only authenticated agents can read (and only that) a resource when gran | Bob | cannot | DELETE | container | R | inherited | 403 | | Public | cannot | DELETE | plain | no | R | 401 | | Public | cannot | DELETE | plain | R | inherited | 401 | - | Public | cannot | DELETE | fictive | no | R | 401 | | Public | cannot | DELETE | fictive | R | inherited | 401 | | Public | cannot | DELETE | rdf | no | R | 401 | | Public | cannot | DELETE | rdf | R | inherited | 401 | diff --git a/web-access-control/protected-operation/read-access-bob.feature b/web-access-control/protected-operation/read-access-bob.feature index 5d2db4d..9a0f064 100644 --- a/web-access-control/protected-operation/read-access-bob.feature +++ b/web-access-control/protected-operation/read-access-bob.feature @@ -48,8 +48,6 @@ Feature: Only Bob can read (and only that) a resource when granted read access const testContainerInheritablePermissions = resourceModes == 'inherited' ? testContainerPermissions - : resourceType == 'fictive' - ? testResourcePermissions : undefined const testContainer = rootTestContainer.createContainer() @@ -80,7 +78,6 @@ Feature: Only Bob can read (and only that) a resource when granted read access | agent | result | method | type | container | resource | status | | Bob | can | GET | plain | no | R | 200 | | Bob | can | GET | plain | R | inherited | 200 | - | Bob | can | GET | fictive | no | R | 404 | | Bob | can | GET | fictive | R | inherited | 404 | | Bob | can | GET | rdf | no | R | 200 | | Bob | can | GET | rdf | R | inherited | 200 | @@ -88,7 +85,6 @@ Feature: Only Bob can read (and only that) a resource when granted read access | Bob | can | GET | container | R | inherited | 200 | | Bob | can | HEAD | plain | no | R | 200 | | Bob | can | HEAD | plain | R | inherited | 200 | - | Bob | can | HEAD | fictive | no | R | 404 | | Bob | can | HEAD | fictive | R | inherited | 404 | | Bob | can | HEAD | rdf | no | R | 200 | | Bob | can | HEAD | rdf | R | inherited | 200 | @@ -96,7 +92,6 @@ Feature: Only Bob can read (and only that) a resource when granted read access | Bob | can | HEAD | container | R | inherited | 200 | | Public | cannot | GET | plain | no | R | 401 | | Public | cannot | GET | plain | R | inherited | 401 | - | Public | cannot | GET | fictive | no | R | 401 | | Public | cannot | GET | fictive | R | inherited | 401 | | Public | cannot | GET | rdf | no | R | 401 | | Public | cannot | GET | rdf | R | inherited | 401 | @@ -104,7 +99,6 @@ Feature: Only Bob can read (and only that) a resource when granted read access | Public | cannot | GET | container | R | inherited | 401 | | Public | cannot | HEAD | plain | no | R | 401 | | Public | cannot | HEAD | plain | R | inherited | 401 | - | Public | cannot | HEAD | fictive | no | R | 401 | | Public | cannot | HEAD | fictive | R | inherited | 401 | | Public | cannot | HEAD | rdf | no | R | 401 | | Public | cannot | HEAD | rdf | R | inherited | 401 | @@ -112,7 +106,6 @@ Feature: Only Bob can read (and only that) a resource when granted read access | Public | cannot | HEAD | container | R | inherited | 401 | | Bob | cannot | GET | plain | no | AWC | 403 | | Bob | cannot | GET | plain | AWC | inherited | 403 | - | Bob | cannot | GET | fictive | no | AWC | 403 | | Bob | cannot | GET | fictive | AWC | inherited | 403 | | Bob | cannot | GET | rdf | no | AWC | 403 | | Bob | cannot | GET | rdf | AWC | inherited | 403 | @@ -120,7 +113,6 @@ Feature: Only Bob can read (and only that) a resource when granted read access | Bob | cannot | GET | container | AWC | inherited | 403 | | Bob | cannot | HEAD | plain | no | AWC | 403 | | Bob | cannot | HEAD | plain | AWC | inherited | 403 | - | Bob | cannot | HEAD | fictive | no | AWC | 403 | | Bob | cannot | HEAD | fictive | AWC | inherited | 403 | | Bob | cannot | HEAD | rdf | no | AWC | 403 | | Bob | cannot | HEAD | rdf | AWC | inherited | 403 | @@ -128,7 +120,6 @@ Feature: Only Bob can read (and only that) a resource when granted read access | Bob | cannot | HEAD | container | AWC | inherited | 403 | | Public | cannot | GET | plain | no | AWC | 401 | | Public | cannot | GET | plain | AWC | inherited | 401 | - | Public | cannot | GET | fictive | no | AWC | 401 | | Public | cannot | GET | fictive | AWC | inherited | 401 | | Public | cannot | GET | rdf | no | AWC | 401 | | Public | cannot | GET | rdf | AWC | inherited | 401 | @@ -136,7 +127,6 @@ Feature: Only Bob can read (and only that) a resource when granted read access | Public | cannot | GET | container | AWC | inherited | 401 | | Public | cannot | HEAD | plain | no | AWC | 401 | | Public | cannot | HEAD | plain | AWC | inherited | 401 | - | Public | cannot | HEAD | fictive | no | AWC | 401 | | Public | cannot | HEAD | fictive | AWC | inherited | 401 | | Public | cannot | HEAD | rdf | no | AWC | 401 | | Public | cannot | HEAD | rdf | AWC | inherited | 401 | @@ -155,25 +145,21 @@ Feature: Only Bob can read (and only that) a resource when granted read access | agent | result | method | type | container | resource | status | | Bob | cannot | PUT | rdf | no | R | 403 | | Bob | cannot | PUT | rdf | R | inherited | 403 | - | Bob | cannot | PUT | fictive | no | R | 403 | | Bob | cannot | PUT | fictive | R | inherited | 403 | | Bob | cannot | PUT | container | no | R | 403 | | Bob | cannot | PUT | container | R | inherited | 403 | | Bob | cannot | POST | rdf | no | R | 403 | | Bob | cannot | POST | rdf | R | inherited | 403 | - | Bob | cannot | POST | fictive | no | R | 404 | | Bob | cannot | POST | fictive | R | inherited | 404 | | Bob | cannot | POST | container | no | R | 403 | | Bob | cannot | POST | container | R | inherited | 403 | | Public | cannot | PUT | rdf | no | R | 401 | | Public | cannot | PUT | rdf | R | inherited | 401 | - | Public | cannot | PUT | fictive | no | R | 401 | | Public | cannot | PUT | fictive | R | inherited | 401 | | Public | cannot | PUT | container | no | R | 401 | | Public | cannot | PUT | container | R | inherited | 401 | | Public | cannot | POST | rdf | no | R | 401 | | Public | cannot | POST | rdf | R | inherited | 401 | - | Public | cannot | POST | fictive | no | R | 401 | | Public | cannot | POST | fictive | R | inherited | 401 | | Public | cannot | POST | container | no | R | 401 | | Public | cannot | POST | container | R | inherited | 401 | @@ -190,13 +176,11 @@ Feature: Only Bob can read (and only that) a resource when granted read access | agent | result | method | type | container | resource | status | | Bob | cannot | PATCH | rdf | no | R | 403 | | Bob | cannot | PATCH | rdf | R | inherited | 403 | - | Bob | cannot | PATCH | fictive | no | R | 403 | | Bob | cannot | PATCH | fictive | R | inherited | 403 | | Bob | cannot | PATCH | container | no | R | 403 | | Bob | cannot | PATCH | container | R | inherited | 403 | | Public | cannot | PATCH | rdf | no | R | 401 | | Public | cannot | PATCH | rdf | R | inherited | 401 | - | Public | cannot | PATCH | fictive | no | R | 401 | | Public | cannot | PATCH | fictive | R | inherited | 401 | | Public | cannot | PATCH | container | no | R | 401 | | Public | cannot | PATCH | container | R | inherited | 401 | @@ -213,27 +197,21 @@ Feature: Only Bob can read (and only that) a resource when granted read access | agent | result | method | type | container | resource | status | | Bob | cannot | PUT | plain | no | R | [403] | | Bob | cannot | PUT | plain | R | inherited | [403] | - | Bob | cannot | PUT | fictive | no | R | [403] | | Bob | cannot | PUT | fictive | R | inherited | [403] | | Bob | cannot | POST | plain | no | R | [403] | | Bob | cannot | POST | plain | R | inherited | [403] | - | Bob | cannot | POST | fictive | no | R | [404] | | Bob | cannot | POST | fictive | R | inherited | [404] | | Bob | cannot | PATCH | plain | no | R | [403, 405, 415] | | Bob | cannot | PATCH | plain | R | inherited | [403, 405, 415] | - | Bob | cannot | PATCH | fictive | no | R | [403, 405, 415] | | Bob | cannot | PATCH | fictive | R | inherited | [403, 405, 415] | | Public | cannot | PUT | plain | no | R | [401] | | Public | cannot | PUT | plain | R | inherited | [401] | - | Public | cannot | PUT | fictive | no | R | [401] | | Public | cannot | PUT | fictive | R | inherited | [401] | | Public | cannot | POST | plain | no | R | [401] | | Public | cannot | POST | plain | R | inherited | [401] | - | Public | cannot | POST | fictive | no | R | [401] | | Public | cannot | POST | fictive | R | inherited | [401] | | Public | cannot | PATCH | plain | no | R | [401, 405, 415] | | Public | cannot | PATCH | plain | R | inherited | [401, 405, 415] | - | Public | cannot | PATCH | fictive | no | R | [401, 405, 415] | | Public | cannot | PATCH | fictive | R | inherited | [401, 405, 415] | Scenario Outline: a resource, when Bob has access to the container and access to the resource @@ -246,7 +224,6 @@ Feature: Only Bob can read (and only that) a resource when granted read access | agent | result | method | type | container | resource | status | | Bob | cannot | DELETE | plain | no | R | 403 | | Bob | cannot | DELETE | plain | R | inherited | 403 | - | Bob | cannot | DELETE | fictive | no | R | 404 | | Bob | cannot | DELETE | fictive | R | inherited | 404 | | Bob | cannot | DELETE | rdf | no | R | 403 | | Bob | cannot | DELETE | rdf | R | inherited | 403 | @@ -254,7 +231,6 @@ Feature: Only Bob can read (and only that) a resource when granted read access | Bob | cannot | DELETE | container | R | inherited | 403 | | Public | cannot | DELETE | plain | no | R | 401 | | Public | cannot | DELETE | plain | R | inherited | 401 | - | Public | cannot | DELETE | fictive | no | R | 401 | | Public | cannot | DELETE | fictive | R | inherited | 401 | | Public | cannot | DELETE | rdf | no | R | 401 | | Public | cannot | DELETE | rdf | R | inherited | 401 | diff --git a/web-access-control/protected-operation/read-access-public.feature b/web-access-control/protected-operation/read-access-public.feature index 46802c5..13af20e 100644 --- a/web-access-control/protected-operation/read-access-public.feature +++ b/web-access-control/protected-operation/read-access-public.feature @@ -47,8 +47,6 @@ Feature: Public agents can read (and only that) a resource when granted read acc const testContainerInheritablePermissions = resourceModes == 'inherited' ? testContainerPermissions - : resourceType == 'fictive' - ? testResourcePermissions : undefined const testContainer = rootTestContainer.createContainer() @@ -79,7 +77,6 @@ Feature: Public agents can read (and only that) a resource when granted read acc | agent | result | method | type | container | resource | status | | Bob | can | GET | plain | no | R | 200 | | Bob | can | GET | plain | R | inherited | 200 | - | Bob | can | GET | fictive | no | R | 404 | | Bob | can | GET | fictive | R | inherited | 404 | | Bob | can | GET | rdf | no | R | 200 | | Bob | can | GET | rdf | R | inherited | 200 | @@ -87,7 +84,6 @@ Feature: Public agents can read (and only that) a resource when granted read acc | Bob | can | GET | container | R | inherited | 200 | | Bob | can | HEAD | plain | no | R | 200 | | Bob | can | HEAD | plain | R | inherited | 200 | - | Bob | can | HEAD | fictive | no | R | 404 | | Bob | can | HEAD | fictive | R | inherited | 404 | | Bob | can | HEAD | rdf | no | R | 200 | | Bob | can | HEAD | rdf | R | inherited | 200 | @@ -95,7 +91,6 @@ Feature: Public agents can read (and only that) a resource when granted read acc | Bob | can | HEAD | container | R | inherited | 200 | | Bob | cannot | GET | plain | no | AWC | 403 | | Bob | cannot | GET | plain | AWC | inherited | 403 | - | Bob | cannot | GET | fictive | no | AWC | 403 | | Bob | cannot | GET | fictive | AWC | inherited | 403 | | Bob | cannot | GET | rdf | no | AWC | 403 | | Bob | cannot | GET | rdf | AWC | inherited | 403 | @@ -103,7 +98,6 @@ Feature: Public agents can read (and only that) a resource when granted read acc | Bob | cannot | GET | container | AWC | inherited | 403 | | Bob | cannot | HEAD | plain | no | AWC | 403 | | Bob | cannot | HEAD | plain | AWC | inherited | 403 | - | Bob | cannot | HEAD | fictive | no | AWC | 403 | | Bob | cannot | HEAD | fictive | AWC | inherited | 403 | | Bob | cannot | HEAD | rdf | no | AWC | 403 | | Bob | cannot | HEAD | rdf | AWC | inherited | 403 | @@ -111,7 +105,6 @@ Feature: Public agents can read (and only that) a resource when granted read acc | Bob | cannot | HEAD | container | AWC | inherited | 403 | | Public | cannot | GET | plain | no | AWC | 401 | | Public | cannot | GET | plain | AWC | inherited | 401 | - | Public | cannot | GET | fictive | no | AWC | 401 | | Public | cannot | GET | fictive | AWC | inherited | 401 | | Public | cannot | GET | rdf | no | AWC | 401 | | Public | cannot | GET | rdf | AWC | inherited | 401 | @@ -119,7 +112,6 @@ Feature: Public agents can read (and only that) a resource when granted read acc | Public | cannot | GET | container | AWC | inherited | 401 | | Public | cannot | HEAD | plain | no | AWC | 401 | | Public | cannot | HEAD | plain | AWC | inherited | 401 | - | Public | cannot | HEAD | fictive | no | AWC | 401 | | Public | cannot | HEAD | fictive | AWC | inherited | 401 | | Public | cannot | HEAD | rdf | no | AWC | 401 | | Public | cannot | HEAD | rdf | AWC | inherited | 401 | @@ -131,7 +123,6 @@ Feature: Public agents can read (and only that) a resource when granted read acc | agent | result | method | type | container | resource | status | | Public | can | GET | plain | no | R | 200 | | Public | can | GET | plain | R | inherited | 200 | - | Public | can | GET | fictive | no | R | 404 | | Public | can | GET | fictive | R | inherited | 404 | | Public | can | GET | rdf | no | R | 200 | | Public | can | GET | rdf | R | inherited | 200 | @@ -139,7 +130,6 @@ Feature: Public agents can read (and only that) a resource when granted read acc | Public | can | GET | container | R | inherited | 200 | | Public | can | HEAD | plain | no | R | 200 | | Public | can | HEAD | plain | R | inherited | 200 | - | Public | can | HEAD | fictive | no | R | 404 | | Public | can | HEAD | fictive | R | inherited | 404 | | Public | can | HEAD | rdf | no | R | 200 | | Public | can | HEAD | rdf | R | inherited | 200 | @@ -158,25 +148,21 @@ Feature: Public agents can read (and only that) a resource when granted read acc | agent | result | method | type | container | resource | status | | Bob | cannot | PUT | rdf | no | R | 403 | | Bob | cannot | PUT | rdf | R | inherited | 403 | - | Bob | cannot | PUT | fictive | no | R | 403 | | Bob | cannot | PUT | fictive | R | inherited | 403 | | Bob | cannot | PUT | container | no | R | 403 | | Bob | cannot | PUT | container | R | inherited | 403 | | Bob | cannot | POST | rdf | no | R | 403 | | Bob | cannot | POST | rdf | R | inherited | 403 | - | Bob | cannot | POST | fictive | no | R | 404 | | Bob | cannot | POST | fictive | R | inherited | 404 | | Bob | cannot | POST | container | no | R | 403 | | Bob | cannot | POST | container | R | inherited | 403 | | Public | cannot | PUT | rdf | no | R | 401 | | Public | cannot | PUT | rdf | R | inherited | 401 | - | Public | cannot | PUT | fictive | no | R | 401 | | Public | cannot | PUT | fictive | R | inherited | 401 | | Public | cannot | PUT | container | no | R | 401 | | Public | cannot | PUT | container | R | inherited | 401 | | Public | cannot | POST | rdf | no | R | 401 | | Public | cannot | POST | rdf | R | inherited | 401 | - | Public | cannot | POST | fictive | no | R | 404 | | Public | cannot | POST | fictive | R | inherited | 404 | | Public | cannot | POST | container | no | R | 401 | | Public | cannot | POST | container | R | inherited | 401 | @@ -193,13 +179,11 @@ Feature: Public agents can read (and only that) a resource when granted read acc | agent | result | method | type | container | resource | status | | Bob | cannot | PATCH | rdf | no | R | 403 | | Bob | cannot | PATCH | rdf | R | inherited | 403 | - | Bob | cannot | PATCH | fictive | no | R | 403 | | Bob | cannot | PATCH | fictive | R | inherited | 403 | | Bob | cannot | PATCH | container | no | R | 403 | | Bob | cannot | PATCH | container | R | inherited | 403 | | Public | cannot | PATCH | rdf | no | R | 401 | | Public | cannot | PATCH | rdf | R | inherited | 401 | - | Public | cannot | PATCH | fictive | no | R | 401 | | Public | cannot | PATCH | fictive | R | inherited | 401 | | Public | cannot | PATCH | container | no | R | 401 | | Public | cannot | PATCH | container | R | inherited | 401 | @@ -216,27 +200,21 @@ Feature: Public agents can read (and only that) a resource when granted read acc | agent | result | method | type | container | resource | status | | Bob | cannot | PUT | plain | no | R | [403] | | Bob | cannot | PUT | plain | R | inherited | [403] | - | Bob | cannot | PUT | fictive | no | R | [403] | | Bob | cannot | PUT | fictive | R | inherited | [403] | | Bob | cannot | POST | plain | no | R | [403] | | Bob | cannot | POST | plain | R | inherited | [403] | - | Bob | cannot | POST | fictive | no | R | [404] | | Bob | cannot | POST | fictive | R | inherited | [404] | | Bob | cannot | PATCH | plain | no | R | [403, 405, 415] | | Bob | cannot | PATCH | plain | R | inherited | [403, 405, 415] | - | Bob | cannot | PATCH | fictive | no | R | [403, 405, 415] | | Bob | cannot | PATCH | fictive | R | inherited | [403, 405, 415] | | Public | cannot | PUT | plain | no | R | [401] | | Public | cannot | PUT | plain | R | inherited | [401] | - | Public | cannot | PUT | fictive | no | R | [401] | | Public | cannot | PUT | fictive | R | inherited | [401] | | Public | cannot | POST | plain | no | R | [401] | | Public | cannot | POST | plain | R | inherited | [401] | - | Public | cannot | POST | fictive | no | R | [404] | | Public | cannot | POST | fictive | R | inherited | [404] | | Public | cannot | PATCH | plain | no | R | [401, 405, 415] | | Public | cannot | PATCH | plain | R | inherited | [401, 405, 415] | - | Public | cannot | PATCH | fictive | no | R | [401, 405, 415] | | Public | cannot | PATCH | fictive | R | inherited | [401, 405, 415] | Scenario Outline: a resource, when a public agent has access to the container and access to the resource @@ -249,7 +227,6 @@ Feature: Public agents can read (and only that) a resource when granted read acc | agent | result | method | type | container | resource | status | | Bob | cannot | DELETE | plain | no | R | 403 | | Bob | cannot | DELETE | plain | R | inherited | 403 | - | Bob | cannot | DELETE | fictive | no | R | 404 | | Bob | cannot | DELETE | fictive | R | inherited | 404 | | Bob | cannot | DELETE | rdf | no | R | 403 | | Bob | cannot | DELETE | rdf | R | inherited | 403 | @@ -257,7 +234,6 @@ Feature: Public agents can read (and only that) a resource when granted read acc | Bob | cannot | DELETE | container | R | inherited | 403 | | Public | cannot | DELETE | plain | no | R | 401 | | Public | cannot | DELETE | plain | R | inherited | 401 | - | Public | cannot | DELETE | fictive | no | R | 404 | | Public | cannot | DELETE | fictive | R | inherited | 404 | | Public | cannot | DELETE | rdf | no | R | 401 | | Public | cannot | DELETE | rdf | R | inherited | 401 | From 926b2fd824d3b52a24c54ddefb655be6233d629a Mon Sep 17 00:00:00 2001 From: surilindur Date: Fri, 19 Aug 2022 18:34:24 +0300 Subject: [PATCH 5/8] added write feature files --- .../read-access-agent.feature | 44 +--- .../read-access-bob.feature | 40 +-- .../read-access-public.feature | 30 +-- .../write-access-agent.feature | 230 +++++++++++++++++ .../write-access-bob.feature | 232 ++++++++++++++++++ .../write-access-public.feature | 186 ++++++++++++++ .../web-access-control-test-manifest.ttl | 21 ++ 7 files changed, 677 insertions(+), 106 deletions(-) create mode 100644 web-access-control/protected-operation/write-access-agent.feature create mode 100644 web-access-control/protected-operation/write-access-bob.feature create mode 100644 web-access-control/protected-operation/write-access-public.feature diff --git a/web-access-control/protected-operation/read-access-agent.feature b/web-access-control/protected-operation/read-access-agent.feature index 5176448..6d8a8b5 100644 --- a/web-access-control/protected-operation/read-access-agent.feature +++ b/web-access-control/protected-operation/read-access-agent.feature @@ -40,7 +40,7 @@ Feature: Only authenticated agents can read (and only that) a resource when gran """ * def createResource = """ - function (containerModes, resourceModes, resourceType, accessMode) { + function (containerModes, resourceModes, resourceType) { const testContainerPermissions = resourcePermissions(containerModes == 'all' ? 'RWAC' : containerModes) const testResourcePermissions = resourcePermissions(resourceModes) @@ -89,48 +89,6 @@ Feature: Only authenticated agents can read (and only that) a resource when gran | Bob | can | HEAD | rdf | R | inherited | 200 | | Bob | can | HEAD | container | no | R | 200 | | Bob | can | HEAD | container | R | inherited | 200 | - | Public | cannot | GET | plain | no | R | 401 | - | Public | cannot | GET | plain | R | inherited | 401 | - | Public | cannot | GET | fictive | R | inherited | 401 | - | Public | cannot | GET | rdf | no | R | 401 | - | Public | cannot | GET | rdf | R | inherited | 401 | - | Public | cannot | GET | container | no | R | 401 | - | Public | cannot | GET | container | R | inherited | 401 | - | Public | cannot | HEAD | plain | no | R | 401 | - | Public | cannot | HEAD | plain | R | inherited | 401 | - | Public | cannot | HEAD | fictive | R | inherited | 401 | - | Public | cannot | HEAD | rdf | no | R | 401 | - | Public | cannot | HEAD | rdf | R | inherited | 401 | - | Public | cannot | HEAD | container | no | R | 401 | - | Public | cannot | HEAD | container | R | inherited | 401 | - | Bob | cannot | GET | plain | no | AWC | 403 | - | Bob | cannot | GET | plain | AWC | inherited | 403 | - | Bob | cannot | GET | fictive | AWC | inherited | 403 | - | Bob | cannot | GET | rdf | no | AWC | 403 | - | Bob | cannot | GET | rdf | AWC | inherited | 403 | - | Bob | cannot | GET | container | no | AWC | 403 | - | Bob | cannot | GET | container | AWC | inherited | 403 | - | Bob | cannot | HEAD | plain | no | AWC | 403 | - | Bob | cannot | HEAD | plain | AWC | inherited | 403 | - | Bob | cannot | HEAD | fictive | AWC | inherited | 403 | - | Bob | cannot | HEAD | rdf | no | AWC | 403 | - | Bob | cannot | HEAD | rdf | AWC | inherited | 403 | - | Bob | cannot | HEAD | container | no | AWC | 403 | - | Bob | cannot | HEAD | container | AWC | inherited | 403 | - | Public | cannot | GET | plain | no | AWC | 401 | - | Public | cannot | GET | plain | AWC | inherited | 401 | - | Public | cannot | GET | fictive | AWC | inherited | 401 | - | Public | cannot | GET | rdf | no | AWC | 401 | - | Public | cannot | GET | rdf | AWC | inherited | 401 | - | Public | cannot | GET | container | no | AWC | 401 | - | Public | cannot | GET | container | AWC | inherited | 401 | - | Public | cannot | HEAD | plain | no | AWC | 401 | - | Public | cannot | HEAD | plain | AWC | inherited | 401 | - | Public | cannot | HEAD | fictive | AWC | inherited | 401 | - | Public | cannot | HEAD | rdf | no | AWC | 401 | - | Public | cannot | HEAD | rdf | AWC | inherited | 401 | - | Public | cannot | HEAD | container | no | AWC | 401 | - | Public | cannot | HEAD | container | AWC | inherited | 401 | Scenario Outline: to a resource, when an authenticated agent has access to the container and access to the resource * def testResource = createResource(container, resource, type) diff --git a/web-access-control/protected-operation/read-access-bob.feature b/web-access-control/protected-operation/read-access-bob.feature index 9a0f064..313fb8e 100644 --- a/web-access-control/protected-operation/read-access-bob.feature +++ b/web-access-control/protected-operation/read-access-bob.feature @@ -40,7 +40,7 @@ Feature: Only Bob can read (and only that) a resource when granted read access """ * def createResource = """ - function (containerModes, resourceModes, resourceType, accessMode) { + function (containerModes, resourceModes, resourceType, agent) { const agentWebId = webIds.bob const testContainerPermissions = resourcePermissions(containerModes == 'all' ? 'RWAC' : containerModes) @@ -69,7 +69,7 @@ Feature: Only Bob can read (and only that) a resource when granted read access """ Scenario Outline: read a resource (), when Bob has access to the container and access to the resource - * def testResource = createResource(container, resource, type) + * def testResource = createResource(container, resource, type, agent) Given url testResource.url And headers authHeaders(method, testResource.url, agent) When method @@ -104,37 +104,9 @@ Feature: Only Bob can read (and only that) a resource when granted read access | Public | cannot | HEAD | rdf | R | inherited | 401 | | Public | cannot | HEAD | container | no | R | 401 | | Public | cannot | HEAD | container | R | inherited | 401 | - | Bob | cannot | GET | plain | no | AWC | 403 | - | Bob | cannot | GET | plain | AWC | inherited | 403 | - | Bob | cannot | GET | fictive | AWC | inherited | 403 | - | Bob | cannot | GET | rdf | no | AWC | 403 | - | Bob | cannot | GET | rdf | AWC | inherited | 403 | - | Bob | cannot | GET | container | no | AWC | 403 | - | Bob | cannot | GET | container | AWC | inherited | 403 | - | Bob | cannot | HEAD | plain | no | AWC | 403 | - | Bob | cannot | HEAD | plain | AWC | inherited | 403 | - | Bob | cannot | HEAD | fictive | AWC | inherited | 403 | - | Bob | cannot | HEAD | rdf | no | AWC | 403 | - | Bob | cannot | HEAD | rdf | AWC | inherited | 403 | - | Bob | cannot | HEAD | container | no | AWC | 403 | - | Bob | cannot | HEAD | container | AWC | inherited | 403 | - | Public | cannot | GET | plain | no | AWC | 401 | - | Public | cannot | GET | plain | AWC | inherited | 401 | - | Public | cannot | GET | fictive | AWC | inherited | 401 | - | Public | cannot | GET | rdf | no | AWC | 401 | - | Public | cannot | GET | rdf | AWC | inherited | 401 | - | Public | cannot | GET | container | no | AWC | 401 | - | Public | cannot | GET | container | AWC | inherited | 401 | - | Public | cannot | HEAD | plain | no | AWC | 401 | - | Public | cannot | HEAD | plain | AWC | inherited | 401 | - | Public | cannot | HEAD | fictive | AWC | inherited | 401 | - | Public | cannot | HEAD | rdf | no | AWC | 401 | - | Public | cannot | HEAD | rdf | AWC | inherited | 401 | - | Public | cannot | HEAD | container | no | AWC | 401 | - | Public | cannot | HEAD | container | AWC | inherited | 401 | Scenario Outline: to a resource, when Bob has access to the container and access to the resource - * def testResource = createResource(container, resource, type) + * def testResource = createResource(container, resource, type, agent) Given url testResource.url And headers authHeaders(method, testResource.url, agent) And header Content-Type = 'text/turtle' @@ -165,7 +137,7 @@ Feature: Only Bob can read (and only that) a resource when granted read access | Public | cannot | POST | container | R | inherited | 401 | Scenario Outline: to a resource, when Bob has access to the container and access to the resource - * def testResource = createResource(container, resource, type) + * def testResource = createResource(container, resource, type, agent) Given url testResource.url And headers authHeaders(method, testResource.url, agent) And header Content-Type = 'text/n3' @@ -186,7 +158,7 @@ Feature: Only Bob can read (and only that) a resource when granted read access | Public | cannot | PATCH | container | R | inherited | 401 | Scenario Outline: to a resource, when Bob has access to the container and access to the resource - * def testResource = createResource(container, resource, type) + * def testResource = createResource(container, resource, type, agent) Given url testResource.url And headers authHeaders(method, testResource.url, agent) And header Content-Type = 'text/plain' @@ -215,7 +187,7 @@ Feature: Only Bob can read (and only that) a resource when granted read access | Public | cannot | PATCH | fictive | R | inherited | [401, 405, 415] | Scenario Outline: a resource, when Bob has access to the container and access to the resource - * def testResource = createResource(container, resource, type) + * def testResource = createResource(container, resource, type, agent) Given url testResource.url And headers authHeaders(method, testResource.url, agent) When method diff --git a/web-access-control/protected-operation/read-access-public.feature b/web-access-control/protected-operation/read-access-public.feature index 13af20e..d0f1bc0 100644 --- a/web-access-control/protected-operation/read-access-public.feature +++ b/web-access-control/protected-operation/read-access-public.feature @@ -40,7 +40,7 @@ Feature: Public agents can read (and only that) a resource when granted read acc """ * def createResource = """ - function (containerModes, resourceModes, resourceType, accessMode) { + function (containerModes, resourceModes, resourceType) { const testContainerPermissions = resourcePermissions(containerModes == 'all' ? 'RWAC' : containerModes) const testResourcePermissions = resourcePermissions(resourceModes) @@ -89,34 +89,6 @@ Feature: Public agents can read (and only that) a resource when granted read acc | Bob | can | HEAD | rdf | R | inherited | 200 | | Bob | can | HEAD | container | no | R | 200 | | Bob | can | HEAD | container | R | inherited | 200 | - | Bob | cannot | GET | plain | no | AWC | 403 | - | Bob | cannot | GET | plain | AWC | inherited | 403 | - | Bob | cannot | GET | fictive | AWC | inherited | 403 | - | Bob | cannot | GET | rdf | no | AWC | 403 | - | Bob | cannot | GET | rdf | AWC | inherited | 403 | - | Bob | cannot | GET | container | no | AWC | 403 | - | Bob | cannot | GET | container | AWC | inherited | 403 | - | Bob | cannot | HEAD | plain | no | AWC | 403 | - | Bob | cannot | HEAD | plain | AWC | inherited | 403 | - | Bob | cannot | HEAD | fictive | AWC | inherited | 403 | - | Bob | cannot | HEAD | rdf | no | AWC | 403 | - | Bob | cannot | HEAD | rdf | AWC | inherited | 403 | - | Bob | cannot | HEAD | container | no | AWC | 403 | - | Bob | cannot | HEAD | container | AWC | inherited | 403 | - | Public | cannot | GET | plain | no | AWC | 401 | - | Public | cannot | GET | plain | AWC | inherited | 401 | - | Public | cannot | GET | fictive | AWC | inherited | 401 | - | Public | cannot | GET | rdf | no | AWC | 401 | - | Public | cannot | GET | rdf | AWC | inherited | 401 | - | Public | cannot | GET | container | no | AWC | 401 | - | Public | cannot | GET | container | AWC | inherited | 401 | - | Public | cannot | HEAD | plain | no | AWC | 401 | - | Public | cannot | HEAD | plain | AWC | inherited | 401 | - | Public | cannot | HEAD | fictive | AWC | inherited | 401 | - | Public | cannot | HEAD | rdf | no | AWC | 401 | - | Public | cannot | HEAD | rdf | AWC | inherited | 401 | - | Public | cannot | HEAD | container | no | AWC | 401 | - | Public | cannot | HEAD | container | AWC | inherited | 401 | @publicagent Examples: diff --git a/web-access-control/protected-operation/write-access-agent.feature b/web-access-control/protected-operation/write-access-agent.feature new file mode 100644 index 0000000..35ddc20 --- /dev/null +++ b/web-access-control/protected-operation/write-access-agent.feature @@ -0,0 +1,230 @@ +Feature: Only authenticated agents can write (and only that) a resource when granted write access + # Grant authenticated agents (setAuthenticatedAccess): + # - restricted access or no access to the parent container + # - restricted access to the test resources, or inherited access for fictive resources + Background: Create test resources with correct access modes + * def authHeaders = + """ + function (method, url, agent) { + const agentLowerCase = agent.toLowerCase() + return agentLowerCase != 'public' ? clients[agentLowerCase].getAuthHeaders(method, url) : {} + } + """ + * def resourcePermissions = + """ + function (modes) { + if (modes && modes != 'inherited' && modes != 'no') { + return Object.entries({ R: 'read', W: 'write', A: 'append', C: 'control' }) + .filter(([mode, permission]) => modes.includes(mode)) + .map(([mode, permission]) => permission) + } + return undefined + } + """ + * def getRequestData = + """ + function (type) { + switch(type) { + case 'rdf': + return { + contentType: 'text/turtle', + requestBody: '<> "Bob replaced it." .', + responseShouldNotContain: "Bob replaced it" + } + default: + return { + contentType: 'text/plain', + requestBody: "Bob's text", + responseShouldNotContain: "Bob's text" + } + } + } + """ + * def resourceEntry = + """ + function (container, type) { + switch (type) { + case 'plain': + return container.createResource('.txt', 'Hello', 'text/plain') + case 'fictive': + return container.reserveResource('.txt') + case 'rdf': + return container.createResource('.ttl', karate.readAsString('../fixtures/example.ttl'), 'text/turtle') + case 'container': + return container.createContainer() + default: + return undefined + } + } + """ + * def createResource = + """ + function (containerModes, resourceModes, resourceType) { + + const testContainerPermissions = resourcePermissions(containerModes == 'all' ? 'RWAC' : containerModes) + const testResourcePermissions = resourcePermissions(resourceModes) + + const testContainerInheritablePermissions = resourceModes == 'inherited' + ? testContainerPermissions + : resourceType == 'fictive' + ? testResourcePermissions + : undefined + + const testContainer = rootTestContainer.createContainer() + const testResource = resourceEntry(testContainer, resourceType) + + testContainer.accessDataset = testContainer.accessDatasetBuilder + .setAuthenticatedAccess(testContainer.url, testContainerPermissions) + .setInheritableAuthenticatedAccess(testContainer.url, testContainerInheritablePermissions) + .build() + + if (resourceType != 'fictive' && resourceModes != 'inherited') { + testResource.accessDataset = testResource.accessDatasetBuilder + .setAuthenticatedAccess(testResource.url, testResourcePermissions) + .build() + } + + return testResource + } + """ + + Scenario Outline: read a resource (), when an authenticated agent has access to the container and access to the resource + * def testResource = createResource(container, resource, type) + Given url testResource.url + And headers authHeaders(method, testResource.url, agent) + When method + Then status + Examples: + | agent | result | method | type | container | resource | status | + | Bob | cannot | GET | plain | no | AWC | 403 | + | Bob | cannot | GET | plain | AWC | inherited | 403 | + | Bob | cannot | GET | fictive | AWC | inherited | 403 | + | Bob | cannot | GET | rdf | no | AWC | 403 | + | Bob | cannot | GET | rdf | AWC | inherited | 403 | + | Bob | cannot | GET | container | no | AWC | 403 | + | Bob | cannot | GET | container | AWC | inherited | 403 | + | Bob | cannot | HEAD | plain | no | AWC | 403 | + | Bob | cannot | HEAD | plain | AWC | inherited | 403 | + | Bob | cannot | HEAD | fictive | AWC | inherited | 403 | + | Bob | cannot | HEAD | rdf | no | AWC | 403 | + | Bob | cannot | HEAD | rdf | AWC | inherited | 403 | + | Bob | cannot | HEAD | container | no | AWC | 403 | + | Bob | cannot | HEAD | container | AWC | inherited | 403 | + | Public | cannot | GET | plain | no | AWC | 401 | + | Public | cannot | GET | plain | AWC | inherited | 401 | + | Public | cannot | GET | fictive | AWC | inherited | 401 | + | Public | cannot | GET | rdf | no | AWC | 401 | + | Public | cannot | GET | rdf | AWC | inherited | 401 | + | Public | cannot | GET | container | no | AWC | 401 | + | Public | cannot | GET | container | AWC | inherited | 401 | + | Public | cannot | HEAD | plain | no | AWC | 401 | + | Public | cannot | HEAD | plain | AWC | inherited | 401 | + | Public | cannot | HEAD | fictive | AWC | inherited | 401 | + | Public | cannot | HEAD | rdf | no | AWC | 401 | + | Public | cannot | HEAD | rdf | AWC | inherited | 401 | + | Public | cannot | HEAD | container | no | AWC | 401 | + | Public | cannot | HEAD | container | AWC | inherited | 401 | + + Scenario Outline: write a resource () and cannot read it, when an authenticated agent has access to the container and access to the resource + * def testResource = createResource(container, resource, type) + * def requestData = getRequestData(type) + Given url testResource.url + And headers authHeaders(method, testResource.url, agent) + And header Content-Type = requestData.contentType + And request requestData.requestBody + When method + Then match contains responseStatus + # Server may return payload with information about the operation e.g. "Created" so check it hasn't leaked the data which was PUT + And string responseString = response + And match responseString !contains requestData.responseShouldNotContain + + Given headers authHeaders('GET', testResource.url, agent) + When method GET + Then status + + Examples: + | agent | result | method | type | container | resource | writeStatus | readStatus | + | Bob | can | PUT | rdf | no | W | [201, 204, 205] | 403 | + | Bob | can | PUT | rdf | W | inherited | [201, 204, 205] | 403 | + | Bob | can | PUT | plain | no | W | [201, 204, 205] | 403 | + | Bob | can | PUT | plain | W | inherited | [201, 204, 205] | 403 | + | Bob | can | PUT | fictive | W | inherited | [201, 204, 205] | 403 | + | Bob | can | POST | container | no | W | [201, 204, 205] | 403 | + | Bob | can | POST | container | W | inherited | [201, 204, 205] | 403 | + | Bob | can | POST | container | no | A | [201, 204, 205] | 403 | + | Bob | can | POST | container | A | inherited | [201, 204, 205] | 403 | + | Public | cannot | PUT | rdf | no | WAC | [401] | 401 | + | Public | cannot | PUT | rdf | WAC | inherited | [401] | 401 | + | Public | cannot | PUT | plain | no | WAC | [401] | 401 | + | Public | cannot | PUT | plain | WAC | inherited | [401] | 401 | + | Public | cannot | PUT | fictive | WAC | inherited | [401] | 401 | + | Public | cannot | POST | container | no | WAC | [401] | 401 | + | Public | cannot | POST | container | WAC | inherited | [401] | 401 | + + Scenario Outline: to a resource, when an authenticated agent has access to the container and access to the resource + * def testResource = createResource(container, resource, type) + Given url testResource.url + And headers authHeaders(method, testResource.url, agent) + And header Content-Type = 'text/n3' + And request '@prefix solid: . _:insert a solid:InsertDeletePatch; solid:inserts { <> a . }.' + When method + Then match contains responseStatus + # Server may return payload with information about the operation e.g. "Created" so check it hasn't leaked the data which was PUT + And string responseString = response + And match responseString !contains 'http://example.org#Foo' + + Given headers authHeaders('GET', testResource.url, agent) + When method GET + Then status + + Examples: + | agent | result | method | type | container | resource | writeStatus | readStatus | + | Bob | can | PATCH | rdf | no | W | [201, 204, 205] | 403 | + | Bob | can | PATCH | rdf | W | inherited | [201, 204, 205] | 403 | + | Bob | can | PATCH | fictive | W | inherited | [201, 204, 205] | 403 | + | Bob | can | PATCH | rdf | no | A | [201, 204, 205] | 403 | + | Bob | can | PATCH | rdf | A | inherited | [201, 204, 205] | 403 | + | Bob | can | PATCH | fictive | A | inherited | [201, 204, 205] | 403 | + | Bob | cannot | PATCH | rdf | no | C | [403] | 403 | + | Bob | cannot | PATCH | rdf | C | inherited | [403] | 403 | + | Bob | cannot | PATCH | fictive | C | inherited | [403] | 403 | + | Public | cannot | PATCH | rdf | no | WAC | [401] | 401 | + | Public | cannot | PATCH | rdf | WAC | inherited | [401] | 401 | + | Public | cannot | PATCH | fictive | WAC | inherited | [401] | 401 | + + Scenario Outline: a resource, when an authenticated agent has access to the container and access to the resource + * def testResource = createResource(container, resource, type) + Given url testResource.url + And headers authHeaders(method, testResource.url, agent) + When method + Then status + Examples: + | agent | result | method | type | container | resource | status | + | Bob | cannot | DELETE | plain | no | C | 403 | + | Bob | cannot | DELETE | plain | C | inherited | 403 | + | Bob | cannot | DELETE | fictive | C | inherited | 403 | + | Bob | cannot | DELETE | rdf | no | C | 403 | + | Bob | cannot | DELETE | rdf | C | inherited | 403 | + | Bob | cannot | DELETE | container | no | C | 403 | + | Bob | cannot | DELETE | container | C | inherited | 403 | + | Bob | cannot | DELETE | plain | no | A | 403 | + | Bob | cannot | DELETE | plain | A | inherited | 403 | + | Bob | cannot | DELETE | fictive | A | inherited | 403 | + | Bob | cannot | DELETE | rdf | no | A | 403 | + | Bob | cannot | DELETE | rdf | A | inherited | 403 | + | Bob | cannot | DELETE | container | no | A | 403 | + | Bob | cannot | DELETE | container | A | inherited | 403 | + | Bob | cannot | DELETE | plain | no | W | 403 | + | Bob | can | DELETE | plain | W | inherited | 205 | + | Bob | cannot | DELETE | fictive | W | inherited | 404 | + | Bob | cannot | DELETE | rdf | no | W | 403 | + | Bob | can | DELETE | rdf | W | inherited | 205 | + | Bob | cannot | DELETE | container | no | W | 403 | + | Bob | cannot | DELETE | container | W | inherited | 403 | + | Public | cannot | DELETE | plain | no | WAC | 401 | + | Public | cannot | DELETE | plain | WAC | inherited | 401 | + | Public | cannot | DELETE | fictive | WAC | inherited | 401 | + | Public | cannot | DELETE | rdf | no | WAC | 401 | + | Public | cannot | DELETE | rdf | WAC | inherited | 401 | + | Public | cannot | DELETE | container | no | WAC | 401 | + | Public | cannot | DELETE | container | WAC | inherited | 401 | diff --git a/web-access-control/protected-operation/write-access-bob.feature b/web-access-control/protected-operation/write-access-bob.feature new file mode 100644 index 0000000..d30589a --- /dev/null +++ b/web-access-control/protected-operation/write-access-bob.feature @@ -0,0 +1,232 @@ +Feature: Only Bob can write (and only that) a resource when granted write access + # Grant a specific agent (setAgentAccess): + # - restricted access or no access to the parent container + # - restricted access to the test resources, or inherited access for fictive resources + Background: Create test resources with correct access modes + * def authHeaders = + """ + function (method, url, agent) { + const agentLowerCase = agent.toLowerCase() + return agentLowerCase != 'public' ? clients[agentLowerCase].getAuthHeaders(method, url) : {} + } + """ + * def resourcePermissions = + """ + function (modes) { + if (modes && modes != 'inherited' && modes != 'no') { + return Object.entries({ R: 'read', W: 'write', A: 'append', C: 'control' }) + .filter(([mode, permission]) => modes.includes(mode)) + .map(([mode, permission]) => permission) + } + return undefined + } + """ + * def getRequestData = + """ + function (type) { + switch(type) { + case 'rdf': + return { + contentType: 'text/turtle', + requestBody: '<> "Bob replaced it." .', + responseShouldNotContain: "Bob replaced it" + } + default: + return { + contentType: 'text/plain', + requestBody: "Bob's text", + responseShouldNotContain: "Bob's text" + } + } + } + """ + * def resourceEntry = + """ + function (container, type) { + switch (type) { + case 'plain': + return container.createResource('.txt', 'Hello', 'text/plain') + case 'fictive': + return container.reserveResource('.txt') + case 'rdf': + return container.createResource('.ttl', karate.readAsString('../fixtures/example.ttl'), 'text/turtle') + case 'container': + return container.createContainer() + default: + return undefined + } + } + """ + * def createResource = + """ + function (containerModes, resourceModes, resourceType, agent) { + + const agentWebId = webIds.bob + + const testContainerPermissions = resourcePermissions(containerModes == 'all' ? 'RWAC' : containerModes) + const testResourcePermissions = resourcePermissions(resourceModes) + + const testContainerInheritablePermissions = resourceModes == 'inherited' + ? testContainerPermissions + : resourceType == 'fictive' + ? testResourcePermissions + : undefined + + const testContainer = rootTestContainer.createContainer() + const testResource = resourceEntry(testContainer, resourceType) + + testContainer.accessDataset = testContainer.accessDatasetBuilder + .setAgentAccess(testContainer.url, agentWebId, testContainerPermissions) + .setInheritableAgentAccess(testContainer.url, agentWebId, testContainerInheritablePermissions) + .build() + + if (resourceType != 'fictive' && resourceModes != 'inherited') { + testResource.accessDataset = testResource.accessDatasetBuilder + .setAgentAccess(testResource.url, agentWebId, testResourcePermissions) + .build() + } + + return testResource + } + """ + + Scenario Outline: read a resource (), when an authenticated agent has access to the container and access to the resource + * def testResource = createResource(container, resource, type) + Given url testResource.url + And headers authHeaders(method, testResource.url, agent) + When method + Then status + Examples: + | agent | result | method | type | container | resource | status | + | Bob | cannot | GET | plain | no | AWC | 403 | + | Bob | cannot | GET | plain | AWC | inherited | 403 | + | Bob | cannot | GET | fictive | AWC | inherited | 403 | + | Bob | cannot | GET | rdf | no | AWC | 403 | + | Bob | cannot | GET | rdf | AWC | inherited | 403 | + | Bob | cannot | GET | container | no | AWC | 403 | + | Bob | cannot | GET | container | AWC | inherited | 403 | + | Bob | cannot | HEAD | plain | no | AWC | 403 | + | Bob | cannot | HEAD | plain | AWC | inherited | 403 | + | Bob | cannot | HEAD | fictive | AWC | inherited | 403 | + | Bob | cannot | HEAD | rdf | no | AWC | 403 | + | Bob | cannot | HEAD | rdf | AWC | inherited | 403 | + | Bob | cannot | HEAD | container | no | AWC | 403 | + | Bob | cannot | HEAD | container | AWC | inherited | 403 | + | Public | cannot | GET | plain | no | AWC | 401 | + | Public | cannot | GET | plain | AWC | inherited | 401 | + | Public | cannot | GET | fictive | AWC | inherited | 401 | + | Public | cannot | GET | rdf | no | AWC | 401 | + | Public | cannot | GET | rdf | AWC | inherited | 401 | + | Public | cannot | GET | container | no | AWC | 401 | + | Public | cannot | GET | container | AWC | inherited | 401 | + | Public | cannot | HEAD | plain | no | AWC | 401 | + | Public | cannot | HEAD | plain | AWC | inherited | 401 | + | Public | cannot | HEAD | fictive | AWC | inherited | 401 | + | Public | cannot | HEAD | rdf | no | AWC | 401 | + | Public | cannot | HEAD | rdf | AWC | inherited | 401 | + | Public | cannot | HEAD | container | no | AWC | 401 | + | Public | cannot | HEAD | container | AWC | inherited | 401 | + + Scenario Outline: write a resource () and cannot read it, when an authenticated agent has access to the container and access to the resource + * def testResource = createResource(container, resource, type) + * def requestData = getRequestData(type) + Given url testResource.url + And headers authHeaders(method, testResource.url, agent) + And header Content-Type = requestData.contentType + And request requestData.requestBody + When method + Then match contains responseStatus + # Server may return payload with information about the operation e.g. "Created" so check it hasn't leaked the data which was PUT + And string responseString = response + And match responseString !contains requestData.responseShouldNotContain + + Given headers authHeaders('GET', testResource.url, agent) + When method GET + Then status + + Examples: + | agent | result | method | type | container | resource | writeStatus | readStatus | + | Bob | can | PUT | rdf | no | W | [201, 204, 205] | 403 | + | Bob | can | PUT | rdf | W | inherited | [201, 204, 205] | 403 | + | Bob | can | PUT | plain | no | W | [201, 204, 205] | 403 | + | Bob | can | PUT | plain | W | inherited | [201, 204, 205] | 403 | + | Bob | can | PUT | fictive | W | inherited | [201, 204, 205] | 403 | + | Bob | can | POST | container | no | W | [201, 204, 205] | 403 | + | Bob | can | POST | container | W | inherited | [201, 204, 205] | 403 | + | Bob | can | POST | container | no | A | [201, 204, 205] | 403 | + | Bob | can | POST | container | A | inherited | [201, 204, 205] | 403 | + | Public | cannot | PUT | rdf | no | WAC | [401] | 401 | + | Public | cannot | PUT | rdf | WAC | inherited | [401] | 401 | + | Public | cannot | PUT | plain | no | WAC | [401] | 401 | + | Public | cannot | PUT | plain | WAC | inherited | [401] | 401 | + | Public | cannot | PUT | fictive | WAC | inherited | [401] | 401 | + | Public | cannot | POST | container | no | WAC | [401] | 401 | + | Public | cannot | POST | container | WAC | inherited | [401] | 401 | + + Scenario Outline: to a resource, when an authenticated agent has access to the container and access to the resource + * def testResource = createResource(container, resource, type) + Given url testResource.url + And headers authHeaders(method, testResource.url, agent) + And header Content-Type = 'text/n3' + And request '@prefix solid: . _:insert a solid:InsertDeletePatch; solid:inserts { <> a . }.' + When method + Then match contains responseStatus + # Server may return payload with information about the operation e.g. "Created" so check it hasn't leaked the data which was PUT + And string responseString = response + And match responseString !contains 'http://example.org#Foo' + + Given headers authHeaders('GET', testResource.url, agent) + When method GET + Then status + + Examples: + | agent | result | method | type | container | resource | writeStatus | readStatus | + | Bob | can | PATCH | rdf | no | W | [201, 204, 205] | 403 | + | Bob | can | PATCH | rdf | W | inherited | [201, 204, 205] | 403 | + | Bob | can | PATCH | fictive | W | inherited | [201, 204, 205] | 403 | + | Bob | can | PATCH | rdf | no | A | [201, 204, 205] | 403 | + | Bob | can | PATCH | rdf | A | inherited | [201, 204, 205] | 403 | + | Bob | can | PATCH | fictive | A | inherited | [201, 204, 205] | 403 | + | Bob | cannot | PATCH | rdf | no | C | [403] | 403 | + | Bob | cannot | PATCH | rdf | C | inherited | [403] | 403 | + | Bob | cannot | PATCH | fictive | C | inherited | [403] | 403 | + | Public | cannot | PATCH | rdf | no | WAC | [401] | 401 | + | Public | cannot | PATCH | rdf | WAC | inherited | [401] | 401 | + | Public | cannot | PATCH | fictive | WAC | inherited | [401] | 401 | + + Scenario Outline: a resource, when an authenticated agent has access to the container and access to the resource + * def testResource = createResource(container, resource, type) + Given url testResource.url + And headers authHeaders(method, testResource.url, agent) + When method + Then status + Examples: + | agent | result | method | type | container | resource | status | + | Bob | cannot | DELETE | plain | no | C | 403 | + | Bob | cannot | DELETE | plain | C | inherited | 403 | + | Bob | cannot | DELETE | fictive | C | inherited | 403 | + | Bob | cannot | DELETE | rdf | no | C | 403 | + | Bob | cannot | DELETE | rdf | C | inherited | 403 | + | Bob | cannot | DELETE | container | no | C | 403 | + | Bob | cannot | DELETE | container | C | inherited | 403 | + | Bob | cannot | DELETE | plain | no | A | 403 | + | Bob | cannot | DELETE | plain | A | inherited | 403 | + | Bob | cannot | DELETE | fictive | A | inherited | 403 | + | Bob | cannot | DELETE | rdf | no | A | 403 | + | Bob | cannot | DELETE | rdf | A | inherited | 403 | + | Bob | cannot | DELETE | container | no | A | 403 | + | Bob | cannot | DELETE | container | A | inherited | 403 | + | Bob | cannot | DELETE | plain | no | W | 403 | + | Bob | can | DELETE | plain | W | inherited | 205 | + | Bob | cannot | DELETE | fictive | W | inherited | 404 | + | Bob | cannot | DELETE | rdf | no | W | 403 | + | Bob | can | DELETE | rdf | W | inherited | 205 | + | Bob | cannot | DELETE | container | no | W | 403 | + | Bob | cannot | DELETE | container | W | inherited | 403 | + | Public | cannot | DELETE | plain | no | WAC | 401 | + | Public | cannot | DELETE | plain | WAC | inherited | 401 | + | Public | cannot | DELETE | fictive | WAC | inherited | 401 | + | Public | cannot | DELETE | rdf | no | WAC | 401 | + | Public | cannot | DELETE | rdf | WAC | inherited | 401 | + | Public | cannot | DELETE | container | no | WAC | 401 | + | Public | cannot | DELETE | container | WAC | inherited | 401 | diff --git a/web-access-control/protected-operation/write-access-public.feature b/web-access-control/protected-operation/write-access-public.feature new file mode 100644 index 0000000..cbadc50 --- /dev/null +++ b/web-access-control/protected-operation/write-access-public.feature @@ -0,0 +1,186 @@ +Feature: Only authenticated agents can write (and only that) a resource when granted write access + # Grant public agents (setPublicAccess): + # - restricted access or no access to the parent container + # - restricted access to the test resources, or inherited access for fictive resources + Background: Create test resources with correct access modes + * def resourcePermissions = + """ + function (modes) { + if (modes && modes != 'inherited' && modes != 'no') { + return Object.entries({ R: 'read', W: 'write', A: 'append', C: 'control' }) + .filter(([mode, permission]) => modes.includes(mode)) + .map(([mode, permission]) => permission) + } + return undefined + } + """ + * def getRequestData = + """ + function (type) { + switch(type) { + case 'rdf': + return { + contentType: 'text/turtle', + requestBody: '<> "Bob replaced it." .', + responseShouldNotContain: "Bob replaced it" + } + default: + return { + contentType: 'text/plain', + requestBody: "Bob's text", + responseShouldNotContain: "Bob's text" + } + } + } + """ + * def resourceEntry = + """ + function (container, type) { + switch (type) { + case 'plain': + return container.createResource('.txt', 'Hello', 'text/plain') + case 'fictive': + return container.reserveResource('.txt') + case 'rdf': + return container.createResource('.ttl', karate.readAsString('../fixtures/example.ttl'), 'text/turtle') + case 'container': + return container.createContainer() + default: + return undefined + } + } + """ + * def createResource = + """ + function (containerModes, resourceModes, resourceType) { + + const testContainerPermissions = resourcePermissions(containerModes == 'all' ? 'RWAC' : containerModes) + const testResourcePermissions = resourcePermissions(resourceModes) + + const testContainerInheritablePermissions = resourceModes == 'inherited' + ? testContainerPermissions + : resourceType == 'fictive' + ? testResourcePermissions + : undefined + + const testContainer = rootTestContainer.createContainer() + const testResource = resourceEntry(testContainer, resourceType) + + testContainer.accessDataset = testContainer.accessDatasetBuilder + .setPublicAccess(testContainer.url, testContainerPermissions) + .setInheritablePublicAccess(testContainer.url, testContainerInheritablePermissions) + .build() + + if (resourceType != 'fictive' && resourceModes != 'inherited') { + testResource.accessDataset = testResource.accessDatasetBuilder + .setPublicAccess(testResource.url, testResourcePermissions) + .build() + } + + return testResource + } + """ + + Scenario Outline: read a resource (), when an authenticated agent has access to the container and access to the resource + * def testResource = createResource(container, resource, type) + Given url testResource.url + When method + Then status + Examples: + | agent | result | method | type | container | resource | status | + | Public | cannot | GET | plain | no | AWC | 401 | + | Public | cannot | GET | plain | AWC | inherited | 401 | + | Public | cannot | GET | fictive | AWC | inherited | 401 | + | Public | cannot | GET | rdf | no | AWC | 401 | + | Public | cannot | GET | rdf | AWC | inherited | 401 | + | Public | cannot | GET | container | no | AWC | 401 | + | Public | cannot | GET | container | AWC | inherited | 401 | + | Public | cannot | HEAD | plain | no | AWC | 401 | + | Public | cannot | HEAD | plain | AWC | inherited | 401 | + | Public | cannot | HEAD | fictive | AWC | inherited | 401 | + | Public | cannot | HEAD | rdf | no | AWC | 401 | + | Public | cannot | HEAD | rdf | AWC | inherited | 401 | + | Public | cannot | HEAD | container | no | AWC | 401 | + | Public | cannot | HEAD | container | AWC | inherited | 401 | + + Scenario Outline: write a resource () and cannot read it, when an authenticated agent has access to the container and access to the resource + * def testResource = createResource(container, resource, type) + * def requestData = getRequestData(type) + Given url testResource.url + And header Content-Type = requestData.contentType + And request requestData.requestBody + When method + Then match contains responseStatus + # Server may return payload with information about the operation e.g. "Created" so check it hasn't leaked the data which was PUT + And string responseString = response + And match responseString !contains requestData.responseShouldNotContain + + When method GET + Then status + + Examples: + | agent | result | method | type | container | resource | writeStatus | readStatus | + | Public | can | PUT | rdf | no | W | [201, 204, 205] | 401 | + | Public | can | PUT | rdf | W | inherited | [201, 204, 205] | 401 | + | Public | can | PUT | plain | no | W | [201, 204, 205] | 401 | + | Public | can | PUT | plain | W | inherited | [201, 204, 205] | 401 | + | Public | can | PUT | fictive | W | inherited | [201, 204, 205] | 401 | + | Public | can | POST | container | no | W | [201, 204, 205] | 401 | + | Public | can | POST | container | W | inherited | [201, 204, 205] | 401 | + | Public | can | POST | container | no | A | [201, 204, 205] | 401 | + | Public | can | POST | container | A | inherited | [201, 204, 205] | 401 | + + Scenario Outline: to a resource, when an authenticated agent has access to the container and access to the resource + * def testResource = createResource(container, resource, type) + Given url testResource.url + And header Content-Type = 'text/n3' + And request '@prefix solid: . _:insert a solid:InsertDeletePatch; solid:inserts { <> a . }.' + When method + Then match contains responseStatus + # Server may return payload with information about the operation e.g. "Created" so check it hasn't leaked the data which was PUT + And string responseString = response + And match responseString !contains 'http://example.org#Foo' + + When method GET + Then status + + Examples: + | agent | result | method | type | container | resource | writeStatus | readStatus | + | Public | can | PATCH | rdf | no | W | [201, 204, 205] | 401 | + | Public | can | PATCH | rdf | W | inherited | [201, 204, 205] | 401 | + | Public | can | PATCH | fictive | W | inherited | [201, 204, 205] | 401 | + | Public | can | PATCH | rdf | no | A | [201, 204, 205] | 401 | + | Public | can | PATCH | rdf | A | inherited | [201, 204, 205] | 401 | + | Public | can | PATCH | fictive | A | inherited | [201, 204, 205] | 401 | + | Public | cannot | PATCH | rdf | no | C | [401] | 401 | + | Public | cannot | PATCH | rdf | C | inherited | [401] | 401 | + | Public | cannot | PATCH | fictive | C | inherited | [401] | 401 | + + Scenario Outline: a resource, when an authenticated agent has access to the container and access to the resource + * def testResource = createResource(container, resource, type) + Given url testResource.url + When method + Then status + Examples: + | agent | result | method | type | container | resource | status | + | Public | cannot | DELETE | plain | no | C | 401 | + | Public | cannot | DELETE | plain | C | inherited | 401 | + | Public | cannot | DELETE | fictive | C | inherited | 401 | + | Public | cannot | DELETE | rdf | no | C | 401 | + | Public | cannot | DELETE | rdf | C | inherited | 401 | + | Public | cannot | DELETE | container | no | C | 401 | + | Public | cannot | DELETE | container | C | inherited | 401 | + | Public | cannot | DELETE | plain | no | A | 401 | + | Public | cannot | DELETE | plain | A | inherited | 401 | + | Public | cannot | DELETE | fictive | A | inherited | 401 | + | Public | cannot | DELETE | rdf | no | A | 401 | + | Public | cannot | DELETE | rdf | A | inherited | 401 | + | Public | cannot | DELETE | container | no | A | 401 | + | Public | cannot | DELETE | container | A | inherited | 401 | + | Public | cannot | DELETE | plain | no | W | 401 | + | Public | can | DELETE | plain | W | inherited | 205 | + | Public | cannot | DELETE | fictive | W | inherited | 404 | + | Public | cannot | DELETE | rdf | no | W | 401 | + | Public | can | DELETE | rdf | W | inherited | 205 | + | Public | cannot | DELETE | container | no | W | 401 | + | Public | cannot | DELETE | container | W | inherited | 401 | diff --git a/web-access-control/web-access-control-test-manifest.ttl b/web-access-control/web-access-control-test-manifest.ttl index c2e7ca6..7876613 100644 --- a/web-access-control/web-access-control-test-manifest.ttl +++ b/web-access-control/web-access-control-test-manifest.ttl @@ -110,3 +110,24 @@ manifest:read-access-public td:reviewStatus td:unreviewed ; spec:testScript . + +manifest:write-access-agent + a td:TestCase ; + spec:requirementReference wac:server-read-operation ; + td:reviewStatus td:unreviewed ; + spec:testScript + . + +manifest:write-access-bob + a td:TestCase ; + spec:requirementReference wac:server-read-operation ; + td:reviewStatus td:unreviewed ; + spec:testScript + . + +manifest:write-access-public + a td:TestCase ; + spec:requirementReference wac:server-read-operation ; + td:reviewStatus td:unreviewed ; + spec:testScript + . From 3ac2177f2834ea590e9e4f7245195aaa576eaac6 Mon Sep 17 00:00:00 2001 From: surilindur Date: Fri, 19 Aug 2022 18:39:48 +0300 Subject: [PATCH 6/8] restored accidentally dropped tests --- .../protected-operation/read-access-agent.feature | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/web-access-control/protected-operation/read-access-agent.feature b/web-access-control/protected-operation/read-access-agent.feature index 6d8a8b5..e6d0749 100644 --- a/web-access-control/protected-operation/read-access-agent.feature +++ b/web-access-control/protected-operation/read-access-agent.feature @@ -89,6 +89,20 @@ Feature: Only authenticated agents can read (and only that) a resource when gran | Bob | can | HEAD | rdf | R | inherited | 200 | | Bob | can | HEAD | container | no | R | 200 | | Bob | can | HEAD | container | R | inherited | 200 | + | Public | cannot | GET | plain | no | R | 401 | + | Public | cannot | GET | plain | R | inherited | 401 | + | Public | cannot | GET | fictive | R | inherited | 401 | + | Public | cannot | GET | rdf | no | R | 401 | + | Public | cannot | GET | rdf | R | inherited | 401 | + | Public | cannot | GET | container | no | R | 401 | + | Public | cannot | GET | container | R | inherited | 401 | + | Public | cannot | HEAD | plain | no | R | 401 | + | Public | cannot | HEAD | plain | R | inherited | 401 | + | Public | cannot | HEAD | fictive | R | inherited | 401 | + | Public | cannot | HEAD | rdf | no | R | 401 | + | Public | cannot | HEAD | rdf | R | inherited | 401 | + | Public | cannot | HEAD | container | no | R | 401 | + | Public | cannot | HEAD | container | R | inherited | 401 | Scenario Outline: to a resource, when an authenticated agent has access to the container and access to the resource * def testResource = createResource(container, resource, type) From 0711e7151f6ad5753b1a8c2dadf46e1d204eda34 Mon Sep 17 00:00:00 2001 From: Pete Edwards Date: Fri, 9 Sep 2022 17:38:56 +0100 Subject: [PATCH 7/8] For read tests reuse same resources and move shared code to use common utils --- run.sh | 2 + .../protected-operation/common.feature | 119 +++++++++ .../read-access-agent.feature | 207 ++++++--------- .../read-access-bob.feature | 208 ++++++--------- .../read-access-public.feature | 207 ++++++--------- .../write-access-agent.feature | 239 ++++++----------- .../write-access-bob.feature | 249 ++++++------------ .../write-access-public.feature | 189 +++++-------- 8 files changed, 585 insertions(+), 835 deletions(-) create mode 100644 web-access-control/protected-operation/common.feature diff --git a/run.sh b/run.sh index 64ec363..0e2184c 100755 --- a/run.sh +++ b/run.sh @@ -99,7 +99,9 @@ EOF stop_css() { echo 'Stopping CSS' docker stop server + echo 'Stopped CSS' docker rm server + echo 'Removed CSS' docker network rm testnet } diff --git a/web-access-control/protected-operation/common.feature b/web-access-control/protected-operation/common.feature new file mode 100644 index 0000000..240cd76 --- /dev/null +++ b/web-access-control/protected-operation/common.feature @@ -0,0 +1,119 @@ +@ignore +Feature: + +Scenario: + * def authHeaders = + """ + function (method, url, agent) { + const agentLowerCase = agent.toLowerCase() + return agentLowerCase !== 'public' ? clients[agentLowerCase].getAuthHeaders(method, url) : {} + } + """ + * def resourcePermissions = + """ + function (modes) { + if (modes && modes !== 'inherited' && modes !== 'no') { + return Object.entries({ R: 'read', W: 'write', A: 'append', C: 'control' }) + .filter(([mode, permission]) => modes.includes(mode)) + .map(([mode, permission]) => permission) + } + return undefined + } + """ + * def getRequestData = + """ + function (type) { + switch(type) { + case 'rdf': + return { + contentType: 'text/turtle', + requestBody: '<> "Bob replaced it." .', + responseShouldNotContain: "Bob replaced it" + } + case 'text/n3': + return { + contentType: 'text/n3', + requestBody: '@prefix solid: . _:insert a solid:InsertDeletePatch; solid:inserts { <> a . }.', + responseShouldNotContain: "http://example.org#Foo" + } + default: + return { + contentType: 'text/plain', + requestBody: "Bob's text", + responseShouldNotContain: "Bob's text" + } + } + } + """ + * def resourceEntry = + """ + function (container, type) { + switch (type) { + case 'plain': + return container.createResource('.txt', 'Hello', 'text/plain') + case 'fictive': + return container.reserveResource('.txt') + case 'rdf': + return container.createResource('.ttl', karate.readAsString('../fixtures/example.ttl'), 'text/turtle') + case 'container': + return container.createContainer() + default: + return undefined + } + } + """ + * def createResource = + """ + function (containerModes, resourceModes, resourceType, subject, agent) { + const testContainerPermissions = resourcePermissions(containerModes) + const testResourcePermissions = resourcePermissions(resourceModes) + const testContainerInheritablePermissions = resourceModes === 'inherited' + ? testContainerPermissions + : undefined + + const testContainer = rootTestContainer.createContainer() + const testResource = resourceEntry(testContainer, resourceType) + + const testContainerAccess = testContainer.accessDatasetBuilder + if (subject === 'agent') { + if (testContainerPermissions) { + testContainerAccess.setAgentAccess(testContainer.url, agent, testContainerPermissions) + } + if (testContainerInheritablePermissions) { + testContainerAccess.setInheritableAgentAccess(testContainer.url, agent, testContainerInheritablePermissions) + } + } else if (subject === 'authenticated') { + if (testContainerPermissions) { + testContainerAccess.setAuthenticatedAccess(testContainer.url, testContainerPermissions) + } + if (testContainerInheritablePermissions) { + testContainerAccess.setInheritableAuthenticatedAccess(testContainer.url, testContainerInheritablePermissions) + } + } else if (subject === 'public') { + if (testContainerPermissions) { + testContainerAccess.setPublicAccess(testContainer.url, testContainerPermissions) + } + if (testContainerInheritablePermissions) { + testContainerAccess.setInheritablePublicAccess(testContainer.url, testContainerInheritablePermissions) + } + } + testContainer.accessDataset = testContainerAccess.build() + + if (resourceType !== 'fictive' && resourceModes !== 'inherited') { + const testResourceAccess = testResource.accessDatasetBuilder + if (testResourcePermissions) { + if (subject === 'agent') { + testResourceAccess.setAgentAccess(testResource.url, agent, testResourcePermissions) + } else if (subject === 'authenticated') { + testResourceAccess.setAuthenticatedAccess(testResource.url, testResourcePermissions) + } else if (subject === 'public') { + testResourceAccess.setPublicAccess(testResource.url, testResourcePermissions) + } + } + testResource.accessDataset = testResourceAccess.build() + } + return testResource + } + """ + * def getResource = (container, resource, type) => testResources[`${container}:${resource}:${type}`] + * def testResources = resources.reduce((map, t) => { map[`${t.container}:${t.resource}:${t.type}`] = createResource(t.container, t.resource, t.type, subject, agent); return map;}, {}) diff --git a/web-access-control/protected-operation/read-access-agent.feature b/web-access-control/protected-operation/read-access-agent.feature index e6d0749..b9d4dd8 100644 --- a/web-access-control/protected-operation/read-access-agent.feature +++ b/web-access-control/protected-operation/read-access-agent.feature @@ -3,74 +3,21 @@ Feature: Only authenticated agents can read (and only that) a resource when gran # - restricted access or no access to the parent container # - restricted access to the test resources, or inherited access for fictive resources Background: Create test resources with correct access modes - * def authHeaders = - """ - function (method, url, agent) { - const agentLowerCase = agent.toLowerCase() - return agentLowerCase != 'public' ? clients[agentLowerCase].getAuthHeaders(method, url) : {} - } - """ - * def resourcePermissions = - """ - function (modes) { - if (modes && modes != 'inherited' && modes != 'no') { - return Object.entries({ R: 'read', W: 'write', A: 'append', C: 'control' }) - .filter(([mode, permission]) => modes.includes(mode)) - .map(([mode, permission]) => permission) - } - return undefined - } - """ - * def resourceEntry = - """ - function (container, type) { - switch (type) { - case 'plain': - return container.createResource('.txt', 'Hello', 'text/plain') - case 'fictive': - return container.reserveResource('.txt') - case 'rdf': - return container.createResource('.ttl', karate.readAsString('../fixtures/example.ttl'), 'text/turtle') - case 'container': - return container.createContainer() - default: - return undefined - } - } - """ - * def createResource = - """ - function (containerModes, resourceModes, resourceType) { - - const testContainerPermissions = resourcePermissions(containerModes == 'all' ? 'RWAC' : containerModes) - const testResourcePermissions = resourcePermissions(resourceModes) - - const testContainerInheritablePermissions = resourceModes == 'inherited' - ? testContainerPermissions - : undefined - - const testContainer = rootTestContainer.createContainer() - const testResource = resourceEntry(testContainer, resourceType) - - testContainer.accessDataset = testContainer.accessDatasetBuilder - .setAuthenticatedAccess(testContainer.url, testContainerPermissions) - .setInheritableAuthenticatedAccess(testContainer.url, testContainerInheritablePermissions) - .build() - - if (resourceType != 'fictive' && resourceModes != 'inherited') { - testResource.accessDataset = testResource.accessDatasetBuilder - .setAuthenticatedAccess(testResource.url, testResourcePermissions) - .build() - } - - return testResource - } - """ + * table resources + | type | container | resource | + | 'plain' | 'no' | 'R' | + | 'plain' | 'R' | 'inherited' | + | 'fictive' | 'R' | 'inherited' | + | 'rdf' | 'no' | 'R' | + | 'rdf' | 'R' | 'inherited' | + | 'container' | 'no' | 'R' | + | 'container' | 'R' | 'inherited' | + * def utils = callonce read('common.feature') ({resources, subject: 'authenticated'}) Scenario Outline: read a resource (), when an authenticated agent has access to the container and access to the resource - * def testResource = createResource(container, resource, type) + * def testResource = utils.getResource(container, resource, type) Given url testResource.url - And headers authHeaders(method, testResource.url, agent) + And headers utils.authHeaders(method, testResource.url, agent) When method Then status Examples: @@ -105,40 +52,40 @@ Feature: Only authenticated agents can read (and only that) a resource when gran | Public | cannot | HEAD | container | R | inherited | 401 | Scenario Outline: to a resource, when an authenticated agent has access to the container and access to the resource - * def testResource = createResource(container, resource, type) + * def testResource = utils.getResource(container, resource, type) Given url testResource.url - And headers authHeaders(method, testResource.url, agent) + And headers utils.authHeaders(method, testResource.url, agent) And header Content-Type = 'text/turtle' And request '@prefix rdfs: . <> rdfs:comment "Bob added this.".' When method - Then status + Then match contains responseStatus Examples: - | agent | result | method | type | container | resource | status | - | Bob | cannot | PUT | rdf | no | R | 403 | - | Bob | cannot | PUT | rdf | R | inherited | 403 | - | Bob | cannot | PUT | fictive | R | inherited | 403 | - | Bob | cannot | PUT | container | no | R | 403 | - | Bob | cannot | PUT | container | R | inherited | 403 | - | Bob | cannot | POST | rdf | no | R | 403 | - | Bob | cannot | POST | rdf | R | inherited | 403 | - | Bob | cannot | POST | fictive | R | inherited | 404 | - | Bob | cannot | POST | container | no | R | 403 | - | Bob | cannot | POST | container | R | inherited | 403 | - | Public | cannot | PUT | rdf | no | R | 401 | - | Public | cannot | PUT | rdf | R | inherited | 401 | - | Public | cannot | PUT | fictive | R | inherited | 401 | - | Public | cannot | PUT | container | no | R | 401 | - | Public | cannot | PUT | container | R | inherited | 401 | - | Public | cannot | POST | rdf | no | R | 401 | - | Public | cannot | POST | rdf | R | inherited | 401 | - | Public | cannot | POST | fictive | R | inherited | 401 | - | Public | cannot | POST | container | no | R | 401 | - | Public | cannot | POST | container | R | inherited | 401 | + | agent | result | method | type | container | resource | status | + | Bob | cannot | PUT | rdf | no | R | [403] | + | Bob | cannot | PUT | rdf | R | inherited | [403] | + | Bob | cannot | PUT | fictive | R | inherited | [403] | + | Bob | cannot | PUT | container | no | R | [403] | + | Bob | cannot | PUT | container | R | inherited | [403] | + | Bob | cannot | POST | rdf | no | R | [403] | + | Bob | cannot | POST | rdf | R | inherited | [403] | + | Bob | cannot | POST | fictive | R | inherited | [403, 404] | + | Bob | cannot | POST | container | no | R | [403] | + | Bob | cannot | POST | container | R | inherited | [403] | + | Public | cannot | PUT | rdf | no | R | [401] | + | Public | cannot | PUT | rdf | R | inherited | [401] | + | Public | cannot | PUT | fictive | R | inherited | [401] | + | Public | cannot | PUT | container | no | R | [401] | + | Public | cannot | PUT | container | R | inherited | [401] | + | Public | cannot | POST | rdf | no | R | [401] | + | Public | cannot | POST | rdf | R | inherited | [401] | + | Public | cannot | POST | fictive | R | inherited | [401] | + | Public | cannot | POST | container | no | R | [401] | + | Public | cannot | POST | container | R | inherited | [401] | Scenario Outline: to a resource, when an authenticated agent has access to the container and access to the resource - * def testResource = createResource(container, resource, type) + * def testResource = utils.getResource(container, resource, type) Given url testResource.url - And headers authHeaders(method, testResource.url, agent) + And headers utils.authHeaders(method, testResource.url, agent) And header Content-Type = 'text/n3' And request '@prefix solid: . _:insert a solid:InsertDeletePatch; solid:inserts { <> a . }.' When method @@ -157,53 +104,53 @@ Feature: Only authenticated agents can read (and only that) a resource when gran | Public | cannot | PATCH | container | R | inherited | 401 | Scenario Outline: to a resource, when an authenticated agent has access to the container and access to the resource - * def testResource = createResource(container, resource, type) + * def testResource = utils.getResource(container, resource, type) Given url testResource.url - And headers authHeaders(method, testResource.url, agent) + And headers utils.authHeaders(method, testResource.url, agent) And header Content-Type = 'text/plain' And request "Bob's text" When method Then match contains responseStatus Examples: - | agent | result | method | type | container | resource | status | - | Bob | cannot | PUT | plain | no | R | [403] | - | Bob | cannot | PUT | plain | R | inherited | [403] | - | Bob | cannot | PUT | fictive | R | inherited | [403] | - | Bob | cannot | POST | plain | no | R | [403] | - | Bob | cannot | POST | plain | R | inherited | [403] | - | Bob | cannot | POST | fictive | R | inherited | [404] | - | Bob | cannot | PATCH | plain | no | R | [403, 405, 415] | - | Bob | cannot | PATCH | plain | R | inherited | [403, 405, 415] | - | Bob | cannot | PATCH | fictive | R | inherited | [403, 405, 415] | - | Public | cannot | PUT | plain | no | R | [401] | - | Public | cannot | PUT | plain | R | inherited | [401] | - | Public | cannot | PUT | fictive | R | inherited | [401] | - | Public | cannot | POST | plain | no | R | [401] | - | Public | cannot | POST | plain | R | inherited | [401] | - | Public | cannot | POST | fictive | R | inherited | [401] | - | Public | cannot | PATCH | plain | no | R | [401, 405, 415] | - | Public | cannot | PATCH | plain | R | inherited | [401, 405, 415] | - | Public | cannot | PATCH | fictive | R | inherited | [401, 405, 415] | + | agent | result | method | type | container | resource | status | + | Bob | cannot | PUT | plain | no | R | [403] | + | Bob | cannot | PUT | plain | R | inherited | [403] | + | Bob | cannot | PUT | fictive | R | inherited | [403] | + | Bob | cannot | POST | plain | no | R | [403] | + | Bob | cannot | POST | plain | R | inherited | [403] | + | Bob | cannot | POST | fictive | R | inherited | [403, 404] | + | Bob | cannot | PATCH | plain | no | R | [403, 405, 415] | + | Bob | cannot | PATCH | plain | R | inherited | [403, 405, 415] | + | Bob | cannot | PATCH | fictive | R | inherited | [403, 405, 415] | + | Public | cannot | PUT | plain | no | R | [401] | + | Public | cannot | PUT | plain | R | inherited | [401] | + | Public | cannot | PUT | fictive | R | inherited | [401] | + | Public | cannot | POST | plain | no | R | [401] | + | Public | cannot | POST | plain | R | inherited | [401] | + | Public | cannot | POST | fictive | R | inherited | [401] | + | Public | cannot | PATCH | plain | no | R | [401, 405, 415] | + | Public | cannot | PATCH | plain | R | inherited | [401, 405, 415] | + | Public | cannot | PATCH | fictive | R | inherited | [401, 405, 415] | Scenario Outline: a resource, when an authenticated agent has access to the container and access to the resource - * def testResource = createResource(container, resource, type) + * def testResource = utils.getResource(container, resource, type) Given url testResource.url - And headers authHeaders(method, testResource.url, agent) + And headers utils.authHeaders(method, testResource.url, agent) When method - Then status + Then match contains responseStatus Examples: - | agent | result | method | type | container | resource | status | - | Bob | cannot | DELETE | plain | no | R | 403 | - | Bob | cannot | DELETE | plain | R | inherited | 403 | - | Bob | cannot | DELETE | fictive | R | inherited | 404 | - | Bob | cannot | DELETE | rdf | no | R | 403 | - | Bob | cannot | DELETE | rdf | R | inherited | 403 | - | Bob | cannot | DELETE | container | no | R | 403 | - | Bob | cannot | DELETE | container | R | inherited | 403 | - | Public | cannot | DELETE | plain | no | R | 401 | - | Public | cannot | DELETE | plain | R | inherited | 401 | - | Public | cannot | DELETE | fictive | R | inherited | 401 | - | Public | cannot | DELETE | rdf | no | R | 401 | - | Public | cannot | DELETE | rdf | R | inherited | 401 | - | Public | cannot | DELETE | container | no | R | 401 | - | Public | cannot | DELETE | container | R | inherited | 401 | + | agent | result | method | type | container | resource | status | + | Bob | cannot | DELETE | plain | no | R | [403] | + | Bob | cannot | DELETE | plain | R | inherited | [403] | + | Bob | cannot | DELETE | fictive | R | inherited | [403, 404] | + | Bob | cannot | DELETE | rdf | no | R | [403] | + | Bob | cannot | DELETE | rdf | R | inherited | [403] | + | Bob | cannot | DELETE | container | no | R | [403] | + | Bob | cannot | DELETE | container | R | inherited | [403] | + | Public | cannot | DELETE | plain | no | R | [401] | + | Public | cannot | DELETE | plain | R | inherited | [401] | + | Public | cannot | DELETE | fictive | R | inherited | [401] | + | Public | cannot | DELETE | rdf | no | R | [401] | + | Public | cannot | DELETE | rdf | R | inherited | [401] | + | Public | cannot | DELETE | container | no | R | [401] | + | Public | cannot | DELETE | container | R | inherited | [401] | diff --git a/web-access-control/protected-operation/read-access-bob.feature b/web-access-control/protected-operation/read-access-bob.feature index 313fb8e..86e6f26 100644 --- a/web-access-control/protected-operation/read-access-bob.feature +++ b/web-access-control/protected-operation/read-access-bob.feature @@ -3,75 +3,21 @@ Feature: Only Bob can read (and only that) a resource when granted read access # - restricted access or no access to the parent container # - restricted access to the test resources, or inherited access for fictive resources Background: Create test resources with correct access modes - * def authHeaders = - """ - function (method, url, agent) { - const agentLowerCase = agent.toLowerCase() - return agentLowerCase != 'public' ? clients[agentLowerCase].getAuthHeaders(method, url) : {} - } - """ - * def resourcePermissions = - """ - function (modes) { - if (modes && modes != 'inherited' && modes != 'no') { - return Object.entries({ R: 'read', W: 'write', A: 'append', C: 'control' }) - .filter(([mode, permission]) => modes.includes(mode)) - .map(([mode, permission]) => permission) - } - return undefined - } - """ - * def resourceEntry = - """ - function (container, type) { - switch (type) { - case 'plain': - return container.createResource('.txt', 'Hello', 'text/plain') - case 'fictive': - return container.reserveResource('.txt') - case 'rdf': - return container.createResource('.ttl', karate.readAsString('../fixtures/example.ttl'), 'text/turtle') - case 'container': - return container.createContainer() - default: - return undefined - } - } - """ - * def createResource = - """ - function (containerModes, resourceModes, resourceType, agent) { - - const agentWebId = webIds.bob - const testContainerPermissions = resourcePermissions(containerModes == 'all' ? 'RWAC' : containerModes) - const testResourcePermissions = resourcePermissions(resourceModes) - - const testContainerInheritablePermissions = resourceModes == 'inherited' - ? testContainerPermissions - : undefined - - const testContainer = rootTestContainer.createContainer() - const testResource = resourceEntry(testContainer, resourceType) - - testContainer.accessDataset = testContainer.accessDatasetBuilder - .setAgentAccess(testContainer.url, agentWebId, testContainerPermissions) - .setInheritableAgentAccess(testContainer.url, agentWebId, testContainerInheritablePermissions) - .build() - - if (resourceType != 'fictive' && resourceModes != 'inherited') { - testResource.accessDataset = testResource.accessDatasetBuilder - .setAgentAccess(testResource.url, agentWebId, testResourcePermissions) - .build() - } - - return testResource - } - """ + * table resources + | type | container | resource | + | 'plain' | 'no' | 'R' | + | 'plain' | 'R' | 'inherited' | + | 'fictive' | 'R' | 'inherited' | + | 'rdf' | 'no' | 'R' | + | 'rdf' | 'R' | 'inherited' | + | 'container' | 'no' | 'R' | + | 'container' | 'R' | 'inherited' | + * def utils = callonce read('common.feature') ({resources, subject: 'agent', agent: webIds.bob}) Scenario Outline: read a resource (), when Bob has access to the container and access to the resource - * def testResource = createResource(container, resource, type, agent) + * def testResource = utils.getResource(container, resource, type) Given url testResource.url - And headers authHeaders(method, testResource.url, agent) + And headers utils.authHeaders(method, testResource.url, agent) When method Then status Examples: @@ -106,40 +52,40 @@ Feature: Only Bob can read (and only that) a resource when granted read access | Public | cannot | HEAD | container | R | inherited | 401 | Scenario Outline: to a resource, when Bob has access to the container and access to the resource - * def testResource = createResource(container, resource, type, agent) + * def testResource = utils.getResource(container, resource, type) Given url testResource.url - And headers authHeaders(method, testResource.url, agent) + And headers utils.authHeaders(method, testResource.url, agent) And header Content-Type = 'text/turtle' And request '@prefix rdfs: . <> rdfs:comment "Bob added this.".' When method - Then status + Then match contains responseStatus Examples: - | agent | result | method | type | container | resource | status | - | Bob | cannot | PUT | rdf | no | R | 403 | - | Bob | cannot | PUT | rdf | R | inherited | 403 | - | Bob | cannot | PUT | fictive | R | inherited | 403 | - | Bob | cannot | PUT | container | no | R | 403 | - | Bob | cannot | PUT | container | R | inherited | 403 | - | Bob | cannot | POST | rdf | no | R | 403 | - | Bob | cannot | POST | rdf | R | inherited | 403 | - | Bob | cannot | POST | fictive | R | inherited | 404 | - | Bob | cannot | POST | container | no | R | 403 | - | Bob | cannot | POST | container | R | inherited | 403 | - | Public | cannot | PUT | rdf | no | R | 401 | - | Public | cannot | PUT | rdf | R | inherited | 401 | - | Public | cannot | PUT | fictive | R | inherited | 401 | - | Public | cannot | PUT | container | no | R | 401 | - | Public | cannot | PUT | container | R | inherited | 401 | - | Public | cannot | POST | rdf | no | R | 401 | - | Public | cannot | POST | rdf | R | inherited | 401 | - | Public | cannot | POST | fictive | R | inherited | 401 | - | Public | cannot | POST | container | no | R | 401 | - | Public | cannot | POST | container | R | inherited | 401 | + | agent | result | method | type | container | resource | status | + | Bob | cannot | PUT | rdf | no | R | [403] | + | Bob | cannot | PUT | rdf | R | inherited | [403] | + | Bob | cannot | PUT | fictive | R | inherited | [403] | + | Bob | cannot | PUT | container | no | R | [403] | + | Bob | cannot | PUT | container | R | inherited | [403] | + | Bob | cannot | POST | rdf | no | R | [403] | + | Bob | cannot | POST | rdf | R | inherited | [403] | + | Bob | cannot | POST | fictive | R | inherited | [403, 404] | + | Bob | cannot | POST | container | no | R | [403] | + | Bob | cannot | POST | container | R | inherited | [403] | + | Public | cannot | PUT | rdf | no | R | [401] | + | Public | cannot | PUT | rdf | R | inherited | [401] | + | Public | cannot | PUT | fictive | R | inherited | [401] | + | Public | cannot | PUT | container | no | R | [401] | + | Public | cannot | PUT | container | R | inherited | [401] | + | Public | cannot | POST | rdf | no | R | [401] | + | Public | cannot | POST | rdf | R | inherited | [401] | + | Public | cannot | POST | fictive | R | inherited | [401] | + | Public | cannot | POST | container | no | R | [401] | + | Public | cannot | POST | container | R | inherited | [401] | Scenario Outline: to a resource, when Bob has access to the container and access to the resource - * def testResource = createResource(container, resource, type, agent) + * def testResource = utils.getResource(container, resource, type) Given url testResource.url - And headers authHeaders(method, testResource.url, agent) + And headers utils.authHeaders(method, testResource.url, agent) And header Content-Type = 'text/n3' And request '@prefix solid: . _:insert a solid:InsertDeletePatch; solid:inserts { <> a . }.' When method @@ -158,53 +104,53 @@ Feature: Only Bob can read (and only that) a resource when granted read access | Public | cannot | PATCH | container | R | inherited | 401 | Scenario Outline: to a resource, when Bob has access to the container and access to the resource - * def testResource = createResource(container, resource, type, agent) + * def testResource = utils.getResource(container, resource, type) Given url testResource.url - And headers authHeaders(method, testResource.url, agent) + And headers utils.authHeaders(method, testResource.url, agent) And header Content-Type = 'text/plain' And request "Bob's text" When method Then match contains responseStatus Examples: - | agent | result | method | type | container | resource | status | - | Bob | cannot | PUT | plain | no | R | [403] | - | Bob | cannot | PUT | plain | R | inherited | [403] | - | Bob | cannot | PUT | fictive | R | inherited | [403] | - | Bob | cannot | POST | plain | no | R | [403] | - | Bob | cannot | POST | plain | R | inherited | [403] | - | Bob | cannot | POST | fictive | R | inherited | [404] | - | Bob | cannot | PATCH | plain | no | R | [403, 405, 415] | - | Bob | cannot | PATCH | plain | R | inherited | [403, 405, 415] | - | Bob | cannot | PATCH | fictive | R | inherited | [403, 405, 415] | - | Public | cannot | PUT | plain | no | R | [401] | - | Public | cannot | PUT | plain | R | inherited | [401] | - | Public | cannot | PUT | fictive | R | inherited | [401] | - | Public | cannot | POST | plain | no | R | [401] | - | Public | cannot | POST | plain | R | inherited | [401] | - | Public | cannot | POST | fictive | R | inherited | [401] | - | Public | cannot | PATCH | plain | no | R | [401, 405, 415] | - | Public | cannot | PATCH | plain | R | inherited | [401, 405, 415] | - | Public | cannot | PATCH | fictive | R | inherited | [401, 405, 415] | + | agent | result | method | type | container | resource | status | + | Bob | cannot | PUT | plain | no | R | [403] | + | Bob | cannot | PUT | plain | R | inherited | [403] | + | Bob | cannot | PUT | fictive | R | inherited | [403] | + | Bob | cannot | POST | plain | no | R | [403] | + | Bob | cannot | POST | plain | R | inherited | [403] | + | Bob | cannot | POST | fictive | R | inherited | [403, 404] | + | Bob | cannot | PATCH | plain | no | R | [403, 405, 415] | + | Bob | cannot | PATCH | plain | R | inherited | [403, 405, 415] | + | Bob | cannot | PATCH | fictive | R | inherited | [403, 405, 415] | + | Public | cannot | PUT | plain | no | R | [401] | + | Public | cannot | PUT | plain | R | inherited | [401] | + | Public | cannot | PUT | fictive | R | inherited | [401] | + | Public | cannot | POST | plain | no | R | [401] | + | Public | cannot | POST | plain | R | inherited | [401] | + | Public | cannot | POST | fictive | R | inherited | [401] | + | Public | cannot | PATCH | plain | no | R | [401, 405, 415] | + | Public | cannot | PATCH | plain | R | inherited | [401, 405, 415] | + | Public | cannot | PATCH | fictive | R | inherited | [401, 405, 415] | Scenario Outline: a resource, when Bob has access to the container and access to the resource - * def testResource = createResource(container, resource, type, agent) + * def testResource = utils.getResource(container, resource, type) Given url testResource.url - And headers authHeaders(method, testResource.url, agent) + And headers utils.authHeaders(method, testResource.url, agent) When method - Then status + Then match contains responseStatus Examples: - | agent | result | method | type | container | resource | status | - | Bob | cannot | DELETE | plain | no | R | 403 | - | Bob | cannot | DELETE | plain | R | inherited | 403 | - | Bob | cannot | DELETE | fictive | R | inherited | 404 | - | Bob | cannot | DELETE | rdf | no | R | 403 | - | Bob | cannot | DELETE | rdf | R | inherited | 403 | - | Bob | cannot | DELETE | container | no | R | 403 | - | Bob | cannot | DELETE | container | R | inherited | 403 | - | Public | cannot | DELETE | plain | no | R | 401 | - | Public | cannot | DELETE | plain | R | inherited | 401 | - | Public | cannot | DELETE | fictive | R | inherited | 401 | - | Public | cannot | DELETE | rdf | no | R | 401 | - | Public | cannot | DELETE | rdf | R | inherited | 401 | - | Public | cannot | DELETE | container | no | R | 401 | - | Public | cannot | DELETE | container | R | inherited | 401 | + | agent | result | method | type | container | resource | status | + | Bob | cannot | DELETE | plain | no | R | [403] | + | Bob | cannot | DELETE | plain | R | inherited | [403] | + | Bob | cannot | DELETE | fictive | R | inherited | [403, 404] | + | Bob | cannot | DELETE | rdf | no | R | [403] | + | Bob | cannot | DELETE | rdf | R | inherited | [403] | + | Bob | cannot | DELETE | container | no | R | [403] | + | Bob | cannot | DELETE | container | R | inherited | [403] | + | Public | cannot | DELETE | plain | no | R | [401] | + | Public | cannot | DELETE | plain | R | inherited | [401] | + | Public | cannot | DELETE | fictive | R | inherited | [401] | + | Public | cannot | DELETE | rdf | no | R | [401] | + | Public | cannot | DELETE | rdf | R | inherited | [401] | + | Public | cannot | DELETE | container | no | R | [401] | + | Public | cannot | DELETE | container | R | inherited | [401] | diff --git a/web-access-control/protected-operation/read-access-public.feature b/web-access-control/protected-operation/read-access-public.feature index d0f1bc0..291a1d0 100644 --- a/web-access-control/protected-operation/read-access-public.feature +++ b/web-access-control/protected-operation/read-access-public.feature @@ -3,74 +3,21 @@ Feature: Public agents can read (and only that) a resource when granted read acc # - restricted access or no access to the parent container # - restricted access to the test resources, or inherited access for fictive resources Background: Create test resources with correct access modes - * def authHeaders = - """ - function (method, url, agent) { - const agentLowerCase = agent.toLowerCase() - return agentLowerCase != 'public' ? clients[agentLowerCase].getAuthHeaders(method, url) : {} - } - """ - * def resourcePermissions = - """ - function (modes) { - if (modes && modes != 'inherited' && modes != 'no') { - return Object.entries({ R: 'read', W: 'write', A: 'append', C: 'control' }) - .filter(([mode, permission]) => modes.includes(mode)) - .map(([mode, permission]) => permission) - } - return undefined - } - """ - * def resourceEntry = - """ - function (container, type) { - switch (type) { - case 'plain': - return container.createResource('.txt', 'Hello', 'text/plain') - case 'fictive': - return container.reserveResource('.txt') - case 'rdf': - return container.createResource('.ttl', karate.readAsString('../fixtures/example.ttl'), 'text/turtle') - case 'container': - return container.createContainer() - default: - return undefined - } - } - """ - * def createResource = - """ - function (containerModes, resourceModes, resourceType) { - - const testContainerPermissions = resourcePermissions(containerModes == 'all' ? 'RWAC' : containerModes) - const testResourcePermissions = resourcePermissions(resourceModes) - - const testContainerInheritablePermissions = resourceModes == 'inherited' - ? testContainerPermissions - : undefined - - const testContainer = rootTestContainer.createContainer() - const testResource = resourceEntry(testContainer, resourceType) - - testContainer.accessDataset = testContainer.accessDatasetBuilder - .setPublicAccess(testContainer.url, testContainerPermissions) - .setInheritablePublicAccess(testContainer.url, testContainerInheritablePermissions) - .build() - - if (resourceType != 'fictive' && resourceModes != 'inherited') { - testResource.accessDataset = testResource.accessDatasetBuilder - .setPublicAccess(testResource.url, testResourcePermissions) - .build() - } - - return testResource - } - """ + * table resources + | type | container | resource | + | 'plain' | 'no' | 'R' | + | 'plain' | 'R' | 'inherited' | + | 'fictive' | 'R' | 'inherited' | + | 'rdf' | 'no' | 'R' | + | 'rdf' | 'R' | 'inherited' | + | 'container' | 'no' | 'R' | + | 'container' | 'R' | 'inherited' | + * def utils = callonce read('common.feature') ({resources, subject: 'public'}) Scenario Outline: read a resource (), when a public agent has access to the container and access to the resource - * def testResource = createResource(container, resource, type) + * def testResource = utils.getResource(container, resource, type) Given url testResource.url - And headers authHeaders(method, testResource.url, agent) + And headers utils.authHeaders(method, testResource.url, agent) When method Then status Examples: @@ -109,40 +56,40 @@ Feature: Public agents can read (and only that) a resource when granted read acc | Public | can | HEAD | container | R | inherited | 200 | Scenario Outline: to a resource, when a public agent has access to the container and access to the resource - * def testResource = createResource(container, resource, type) + * def testResource = utils.getResource(container, resource, type) Given url testResource.url - And headers authHeaders(method, testResource.url, agent) + And headers utils.authHeaders(method, testResource.url, agent) And header Content-Type = 'text/turtle' And request '@prefix rdfs: . <> rdfs:comment "Bob added this.".' When method - Then status + Then match contains responseStatus Examples: - | agent | result | method | type | container | resource | status | - | Bob | cannot | PUT | rdf | no | R | 403 | - | Bob | cannot | PUT | rdf | R | inherited | 403 | - | Bob | cannot | PUT | fictive | R | inherited | 403 | - | Bob | cannot | PUT | container | no | R | 403 | - | Bob | cannot | PUT | container | R | inherited | 403 | - | Bob | cannot | POST | rdf | no | R | 403 | - | Bob | cannot | POST | rdf | R | inherited | 403 | - | Bob | cannot | POST | fictive | R | inherited | 404 | - | Bob | cannot | POST | container | no | R | 403 | - | Bob | cannot | POST | container | R | inherited | 403 | - | Public | cannot | PUT | rdf | no | R | 401 | - | Public | cannot | PUT | rdf | R | inherited | 401 | - | Public | cannot | PUT | fictive | R | inherited | 401 | - | Public | cannot | PUT | container | no | R | 401 | - | Public | cannot | PUT | container | R | inherited | 401 | - | Public | cannot | POST | rdf | no | R | 401 | - | Public | cannot | POST | rdf | R | inherited | 401 | - | Public | cannot | POST | fictive | R | inherited | 404 | - | Public | cannot | POST | container | no | R | 401 | - | Public | cannot | POST | container | R | inherited | 401 | + | agent | result | method | type | container | resource | status | + | Bob | cannot | PUT | rdf | no | R | [403] | + | Bob | cannot | PUT | rdf | R | inherited | [403] | + | Bob | cannot | PUT | fictive | R | inherited | [403] | + | Bob | cannot | PUT | container | no | R | [403] | + | Bob | cannot | PUT | container | R | inherited | [403] | + | Bob | cannot | POST | rdf | no | R | [403] | + | Bob | cannot | POST | rdf | R | inherited | [403] | + | Bob | cannot | POST | fictive | R | inherited | [403, 404] | + | Bob | cannot | POST | container | no | R | [403] | + | Bob | cannot | POST | container | R | inherited | [403] | + | Public | cannot | PUT | rdf | no | R | [401] | + | Public | cannot | PUT | rdf | R | inherited | [401] | + | Public | cannot | PUT | fictive | R | inherited | [401] | + | Public | cannot | PUT | container | no | R | [401] | + | Public | cannot | PUT | container | R | inherited | [401] | + | Public | cannot | POST | rdf | no | R | [401] | + | Public | cannot | POST | rdf | R | inherited | [401] | + | Public | cannot | POST | fictive | R | inherited | [401, 404] | + | Public | cannot | POST | container | no | R | [401] | + | Public | cannot | POST | container | R | inherited | [401] | Scenario Outline: to a resource, when a public agent has access to the container and access to the resource - * def testResource = createResource(container, resource, type) + * def testResource = utils.getResource(container, resource, type) Given url testResource.url - And headers authHeaders(method, testResource.url, agent) + And headers utils.authHeaders(method, testResource.url, agent) And header Content-Type = 'text/n3' And request '@prefix solid: . _:insert a solid:InsertDeletePatch; solid:inserts { <> a . }.' When method @@ -161,53 +108,53 @@ Feature: Public agents can read (and only that) a resource when granted read acc | Public | cannot | PATCH | container | R | inherited | 401 | Scenario Outline: to a resource, when a public agent has access to the container and access to the resource - * def testResource = createResource(container, resource, type) + * def testResource = utils.getResource(container, resource, type) Given url testResource.url - And headers authHeaders(method, testResource.url, agent) + And headers utils.authHeaders(method, testResource.url, agent) And header Content-Type = 'text/plain' And request "Bob's text" When method Then match contains responseStatus Examples: - | agent | result | method | type | container | resource | status | - | Bob | cannot | PUT | plain | no | R | [403] | - | Bob | cannot | PUT | plain | R | inherited | [403] | - | Bob | cannot | PUT | fictive | R | inherited | [403] | - | Bob | cannot | POST | plain | no | R | [403] | - | Bob | cannot | POST | plain | R | inherited | [403] | - | Bob | cannot | POST | fictive | R | inherited | [404] | - | Bob | cannot | PATCH | plain | no | R | [403, 405, 415] | - | Bob | cannot | PATCH | plain | R | inherited | [403, 405, 415] | - | Bob | cannot | PATCH | fictive | R | inherited | [403, 405, 415] | - | Public | cannot | PUT | plain | no | R | [401] | - | Public | cannot | PUT | plain | R | inherited | [401] | - | Public | cannot | PUT | fictive | R | inherited | [401] | - | Public | cannot | POST | plain | no | R | [401] | - | Public | cannot | POST | plain | R | inherited | [401] | - | Public | cannot | POST | fictive | R | inherited | [404] | - | Public | cannot | PATCH | plain | no | R | [401, 405, 415] | - | Public | cannot | PATCH | plain | R | inherited | [401, 405, 415] | - | Public | cannot | PATCH | fictive | R | inherited | [401, 405, 415] | + | agent | result | method | type | container | resource | status | + | Bob | cannot | PUT | plain | no | R | [403] | + | Bob | cannot | PUT | plain | R | inherited | [403] | + | Bob | cannot | PUT | fictive | R | inherited | [403] | + | Bob | cannot | POST | plain | no | R | [403] | + | Bob | cannot | POST | plain | R | inherited | [403] | + | Bob | cannot | POST | fictive | R | inherited | [403, 404] | + | Bob | cannot | PATCH | plain | no | R | [403, 405, 415] | + | Bob | cannot | PATCH | plain | R | inherited | [403, 405, 415] | + | Bob | cannot | PATCH | fictive | R | inherited | [403, 405, 415] | + | Public | cannot | PUT | plain | no | R | [401] | + | Public | cannot | PUT | plain | R | inherited | [401] | + | Public | cannot | PUT | fictive | R | inherited | [401] | + | Public | cannot | POST | plain | no | R | [401] | + | Public | cannot | POST | plain | R | inherited | [401] | + | Public | cannot | POST | fictive | R | inherited | [401, 404] | + | Public | cannot | PATCH | plain | no | R | [401, 405, 415] | + | Public | cannot | PATCH | plain | R | inherited | [401, 405, 415] | + | Public | cannot | PATCH | fictive | R | inherited | [401, 405, 415] | Scenario Outline: a resource, when a public agent has access to the container and access to the resource - * def testResource = createResource(container, resource, type) + * def testResource = utils.getResource(container, resource, type) Given url testResource.url - And headers authHeaders(method, testResource.url, agent) + And headers utils.authHeaders(method, testResource.url, agent) When method - Then status + Then match contains responseStatus Examples: - | agent | result | method | type | container | resource | status | - | Bob | cannot | DELETE | plain | no | R | 403 | - | Bob | cannot | DELETE | plain | R | inherited | 403 | - | Bob | cannot | DELETE | fictive | R | inherited | 404 | - | Bob | cannot | DELETE | rdf | no | R | 403 | - | Bob | cannot | DELETE | rdf | R | inherited | 403 | - | Bob | cannot | DELETE | container | no | R | 403 | - | Bob | cannot | DELETE | container | R | inherited | 403 | - | Public | cannot | DELETE | plain | no | R | 401 | - | Public | cannot | DELETE | plain | R | inherited | 401 | - | Public | cannot | DELETE | fictive | R | inherited | 404 | - | Public | cannot | DELETE | rdf | no | R | 401 | - | Public | cannot | DELETE | rdf | R | inherited | 401 | - | Public | cannot | DELETE | container | no | R | 401 | - | Public | cannot | DELETE | container | R | inherited | 401 | + | agent | result | method | type | container | resource | status | + | Bob | cannot | DELETE | plain | no | R | [403] | + | Bob | cannot | DELETE | plain | R | inherited | [403] | + | Bob | cannot | DELETE | fictive | R | inherited | [403, 404] | + | Bob | cannot | DELETE | rdf | no | R | [403] | + | Bob | cannot | DELETE | rdf | R | inherited | [403] | + | Bob | cannot | DELETE | container | no | R | [403] | + | Bob | cannot | DELETE | container | R | inherited | [403] | + | Public | cannot | DELETE | plain | no | R | [401] | + | Public | cannot | DELETE | plain | R | inherited | [401] | + | Public | cannot | DELETE | fictive | R | inherited | [401, 404] | + | Public | cannot | DELETE | rdf | no | R | [401] | + | Public | cannot | DELETE | rdf | R | inherited | [401] | + | Public | cannot | DELETE | container | no | R | [401] | + | Public | cannot | DELETE | container | R | inherited | [401] | diff --git a/web-access-control/protected-operation/write-access-agent.feature b/web-access-control/protected-operation/write-access-agent.feature index 35ddc20..346a918 100644 --- a/web-access-control/protected-operation/write-access-agent.feature +++ b/web-access-control/protected-operation/write-access-agent.feature @@ -3,133 +3,59 @@ Feature: Only authenticated agents can write (and only that) a resource when gra # - restricted access or no access to the parent container # - restricted access to the test resources, or inherited access for fictive resources Background: Create test resources with correct access modes - * def authHeaders = - """ - function (method, url, agent) { - const agentLowerCase = agent.toLowerCase() - return agentLowerCase != 'public' ? clients[agentLowerCase].getAuthHeaders(method, url) : {} - } - """ - * def resourcePermissions = - """ - function (modes) { - if (modes && modes != 'inherited' && modes != 'no') { - return Object.entries({ R: 'read', W: 'write', A: 'append', C: 'control' }) - .filter(([mode, permission]) => modes.includes(mode)) - .map(([mode, permission]) => permission) - } - return undefined - } - """ - * def getRequestData = - """ - function (type) { - switch(type) { - case 'rdf': - return { - contentType: 'text/turtle', - requestBody: '<> "Bob replaced it." .', - responseShouldNotContain: "Bob replaced it" - } - default: - return { - contentType: 'text/plain', - requestBody: "Bob's text", - responseShouldNotContain: "Bob's text" - } - } - } - """ - * def resourceEntry = - """ - function (container, type) { - switch (type) { - case 'plain': - return container.createResource('.txt', 'Hello', 'text/plain') - case 'fictive': - return container.reserveResource('.txt') - case 'rdf': - return container.createResource('.ttl', karate.readAsString('../fixtures/example.ttl'), 'text/turtle') - case 'container': - return container.createContainer() - default: - return undefined - } - } - """ - * def createResource = - """ - function (containerModes, resourceModes, resourceType) { - - const testContainerPermissions = resourcePermissions(containerModes == 'all' ? 'RWAC' : containerModes) - const testResourcePermissions = resourcePermissions(resourceModes) - - const testContainerInheritablePermissions = resourceModes == 'inherited' - ? testContainerPermissions - : resourceType == 'fictive' - ? testResourcePermissions - : undefined - - const testContainer = rootTestContainer.createContainer() - const testResource = resourceEntry(testContainer, resourceType) - - testContainer.accessDataset = testContainer.accessDatasetBuilder - .setAuthenticatedAccess(testContainer.url, testContainerPermissions) - .setInheritableAuthenticatedAccess(testContainer.url, testContainerInheritablePermissions) - .build() - - if (resourceType != 'fictive' && resourceModes != 'inherited') { - testResource.accessDataset = testResource.accessDatasetBuilder - .setAuthenticatedAccess(testResource.url, testResourcePermissions) - .build() - } - - return testResource - } - """ + * table resources + | type | container | resource | + | 'plain' | 'no' | 'WAC' | + | 'plain' | 'WAC' | 'inherited' | + | 'fictive' | 'WAC' | 'inherited' | + | 'rdf' | 'no' | 'WAC' | + | 'rdf' | 'WAC' | 'inherited' | + | 'container' | 'no' | 'WAC' | + | 'container' | 'WAC' | 'inherited' | + * def utils = callonce read('common.feature') ({resources, subject: 'authenticated'}) Scenario Outline: read a resource (), when an authenticated agent has access to the container and access to the resource - * def testResource = createResource(container, resource, type) + * def testResource = utils.getResource(container, resource, type) Given url testResource.url - And headers authHeaders(method, testResource.url, agent) + And headers utils.authHeaders(method, testResource.url, agent) When method Then status Examples: | agent | result | method | type | container | resource | status | - | Bob | cannot | GET | plain | no | AWC | 403 | - | Bob | cannot | GET | plain | AWC | inherited | 403 | - | Bob | cannot | GET | fictive | AWC | inherited | 403 | - | Bob | cannot | GET | rdf | no | AWC | 403 | - | Bob | cannot | GET | rdf | AWC | inherited | 403 | - | Bob | cannot | GET | container | no | AWC | 403 | - | Bob | cannot | GET | container | AWC | inherited | 403 | - | Bob | cannot | HEAD | plain | no | AWC | 403 | - | Bob | cannot | HEAD | plain | AWC | inherited | 403 | - | Bob | cannot | HEAD | fictive | AWC | inherited | 403 | - | Bob | cannot | HEAD | rdf | no | AWC | 403 | - | Bob | cannot | HEAD | rdf | AWC | inherited | 403 | - | Bob | cannot | HEAD | container | no | AWC | 403 | - | Bob | cannot | HEAD | container | AWC | inherited | 403 | - | Public | cannot | GET | plain | no | AWC | 401 | - | Public | cannot | GET | plain | AWC | inherited | 401 | - | Public | cannot | GET | fictive | AWC | inherited | 401 | - | Public | cannot | GET | rdf | no | AWC | 401 | - | Public | cannot | GET | rdf | AWC | inherited | 401 | - | Public | cannot | GET | container | no | AWC | 401 | - | Public | cannot | GET | container | AWC | inherited | 401 | - | Public | cannot | HEAD | plain | no | AWC | 401 | - | Public | cannot | HEAD | plain | AWC | inherited | 401 | - | Public | cannot | HEAD | fictive | AWC | inherited | 401 | - | Public | cannot | HEAD | rdf | no | AWC | 401 | - | Public | cannot | HEAD | rdf | AWC | inherited | 401 | - | Public | cannot | HEAD | container | no | AWC | 401 | - | Public | cannot | HEAD | container | AWC | inherited | 401 | + | Bob | cannot | GET | plain | no | WAC | 403 | + | Bob | cannot | GET | plain | WAC | inherited | 403 | + | Bob | cannot | GET | fictive | WAC | inherited | 403 | + | Bob | cannot | GET | rdf | no | WAC | 403 | + | Bob | cannot | GET | rdf | WAC | inherited | 403 | + | Bob | cannot | GET | container | no | WAC | 403 | + | Bob | cannot | GET | container | WAC | inherited | 403 | + | Bob | cannot | HEAD | plain | no | WAC | 403 | + | Bob | cannot | HEAD | plain | WAC | inherited | 403 | + | Bob | cannot | HEAD | fictive | WAC | inherited | 403 | + | Bob | cannot | HEAD | rdf | no | WAC | 403 | + | Bob | cannot | HEAD | rdf | WAC | inherited | 403 | + | Bob | cannot | HEAD | container | no | WAC | 403 | + | Bob | cannot | HEAD | container | WAC | inherited | 403 | + | Public | cannot | GET | plain | no | WAC | 401 | + | Public | cannot | GET | plain | WAC | inherited | 401 | + | Public | cannot | GET | fictive | WAC | inherited | 401 | + | Public | cannot | GET | rdf | no | WAC | 401 | + | Public | cannot | GET | rdf | WAC | inherited | 401 | + | Public | cannot | GET | container | no | WAC | 401 | + | Public | cannot | GET | container | WAC | inherited | 401 | + | Public | cannot | HEAD | plain | no | WAC | 401 | + | Public | cannot | HEAD | plain | WAC | inherited | 401 | + | Public | cannot | HEAD | fictive | WAC | inherited | 401 | + | Public | cannot | HEAD | rdf | no | WAC | 401 | + | Public | cannot | HEAD | rdf | WAC | inherited | 401 | + | Public | cannot | HEAD | container | no | WAC | 401 | + | Public | cannot | HEAD | container | WAC | inherited | 401 | Scenario Outline: write a resource () and cannot read it, when an authenticated agent has access to the container and access to the resource - * def testResource = createResource(container, resource, type) - * def requestData = getRequestData(type) + * def testResource = utils.createResource(container, resource, type, 'authenticated') + * def requestData = utils.getRequestData(type) Given url testResource.url - And headers authHeaders(method, testResource.url, agent) + And headers utils.authHeaders(method, testResource.url, agent) And header Content-Type = requestData.contentType And request requestData.requestBody When method @@ -138,7 +64,7 @@ Feature: Only authenticated agents can write (and only that) a resource when gra And string responseString = response And match responseString !contains requestData.responseShouldNotContain - Given headers authHeaders('GET', testResource.url, agent) + Given headers utils.authHeaders('GET', testResource.url, agent) When method GET Then status @@ -162,18 +88,19 @@ Feature: Only authenticated agents can write (and only that) a resource when gra | Public | cannot | POST | container | WAC | inherited | [401] | 401 | Scenario Outline: to a resource, when an authenticated agent has access to the container and access to the resource - * def testResource = createResource(container, resource, type) + * def testResource = utils.createResource(container, resource, type, 'authenticated') + * def requestData = utils.getRequestData('text/n3') Given url testResource.url - And headers authHeaders(method, testResource.url, agent) - And header Content-Type = 'text/n3' - And request '@prefix solid: . _:insert a solid:InsertDeletePatch; solid:inserts { <> a . }.' + And headers utils.authHeaders(method, testResource.url, agent) + And header Content-Type = requestData.contentType + And request requestData.requestBody When method Then match contains responseStatus # Server may return payload with information about the operation e.g. "Created" so check it hasn't leaked the data which was PUT And string responseString = response - And match responseString !contains 'http://example.org#Foo' + And match responseString !contains requestData.responseShouldNotContain - Given headers authHeaders('GET', testResource.url, agent) + Given headers utils.authHeaders('GET', testResource.url, agent) When method GET Then status @@ -193,38 +120,38 @@ Feature: Only authenticated agents can write (and only that) a resource when gra | Public | cannot | PATCH | fictive | WAC | inherited | [401] | 401 | Scenario Outline: a resource, when an authenticated agent has access to the container and access to the resource - * def testResource = createResource(container, resource, type) + * def testResource = utils.createResource(container, resource, type, 'authenticated') Given url testResource.url - And headers authHeaders(method, testResource.url, agent) + And headers utils.authHeaders(method, testResource.url, agent) When method - Then status + Then match contains responseStatus Examples: - | agent | result | method | type | container | resource | status | - | Bob | cannot | DELETE | plain | no | C | 403 | - | Bob | cannot | DELETE | plain | C | inherited | 403 | - | Bob | cannot | DELETE | fictive | C | inherited | 403 | - | Bob | cannot | DELETE | rdf | no | C | 403 | - | Bob | cannot | DELETE | rdf | C | inherited | 403 | - | Bob | cannot | DELETE | container | no | C | 403 | - | Bob | cannot | DELETE | container | C | inherited | 403 | - | Bob | cannot | DELETE | plain | no | A | 403 | - | Bob | cannot | DELETE | plain | A | inherited | 403 | - | Bob | cannot | DELETE | fictive | A | inherited | 403 | - | Bob | cannot | DELETE | rdf | no | A | 403 | - | Bob | cannot | DELETE | rdf | A | inherited | 403 | - | Bob | cannot | DELETE | container | no | A | 403 | - | Bob | cannot | DELETE | container | A | inherited | 403 | - | Bob | cannot | DELETE | plain | no | W | 403 | - | Bob | can | DELETE | plain | W | inherited | 205 | - | Bob | cannot | DELETE | fictive | W | inherited | 404 | - | Bob | cannot | DELETE | rdf | no | W | 403 | - | Bob | can | DELETE | rdf | W | inherited | 205 | - | Bob | cannot | DELETE | container | no | W | 403 | - | Bob | cannot | DELETE | container | W | inherited | 403 | - | Public | cannot | DELETE | plain | no | WAC | 401 | - | Public | cannot | DELETE | plain | WAC | inherited | 401 | - | Public | cannot | DELETE | fictive | WAC | inherited | 401 | - | Public | cannot | DELETE | rdf | no | WAC | 401 | - | Public | cannot | DELETE | rdf | WAC | inherited | 401 | - | Public | cannot | DELETE | container | no | WAC | 401 | - | Public | cannot | DELETE | container | WAC | inherited | 401 | + | agent | result | method | type | container | resource | status | + | Bob | cannot | DELETE | plain | no | C | [403] | + | Bob | cannot | DELETE | plain | C | inherited | [403] | + | Bob | cannot | DELETE | fictive | C | inherited | [403] | + | Bob | cannot | DELETE | rdf | no | C | [403] | + | Bob | cannot | DELETE | rdf | C | inherited | [403] | + | Bob | cannot | DELETE | container | no | C | [403] | + | Bob | cannot | DELETE | container | C | inherited | [403] | + | Bob | cannot | DELETE | plain | no | A | [403] | + | Bob | cannot | DELETE | plain | A | inherited | [403] | + | Bob | cannot | DELETE | fictive | A | inherited | [403] | + | Bob | cannot | DELETE | rdf | no | A | [403] | + | Bob | cannot | DELETE | rdf | A | inherited | [403] | + | Bob | cannot | DELETE | container | no | A | [403] | + | Bob | cannot | DELETE | container | A | inherited | [403] | + | Bob | cannot | DELETE | plain | no | W | [403] | + | Bob | can | DELETE | plain | W | inherited | [200, 202, 204, 205] | + | Bob | cannot | DELETE | fictive | W | inherited | [403] | + | Bob | cannot | DELETE | rdf | no | W | [403] | + | Bob | can | DELETE | rdf | W | inherited | [200, 202, 204, 205] | + | Bob | cannot | DELETE | container | no | W | [403] | + | Bob | cannot | DELETE | container | W | inherited | [403] | + | Public | cannot | DELETE | plain | no | WAC | [401] | + | Public | cannot | DELETE | plain | WAC | inherited | [401] | + | Public | cannot | DELETE | fictive | WAC | inherited | [401] | + | Public | cannot | DELETE | rdf | no | WAC | [401] | + | Public | cannot | DELETE | rdf | WAC | inherited | [401] | + | Public | cannot | DELETE | container | no | WAC | [401] | + | Public | cannot | DELETE | container | WAC | inherited | [401] | diff --git a/web-access-control/protected-operation/write-access-bob.feature b/web-access-control/protected-operation/write-access-bob.feature index d30589a..511917f 100644 --- a/web-access-control/protected-operation/write-access-bob.feature +++ b/web-access-control/protected-operation/write-access-bob.feature @@ -3,135 +3,59 @@ Feature: Only Bob can write (and only that) a resource when granted write access # - restricted access or no access to the parent container # - restricted access to the test resources, or inherited access for fictive resources Background: Create test resources with correct access modes - * def authHeaders = - """ - function (method, url, agent) { - const agentLowerCase = agent.toLowerCase() - return agentLowerCase != 'public' ? clients[agentLowerCase].getAuthHeaders(method, url) : {} - } - """ - * def resourcePermissions = - """ - function (modes) { - if (modes && modes != 'inherited' && modes != 'no') { - return Object.entries({ R: 'read', W: 'write', A: 'append', C: 'control' }) - .filter(([mode, permission]) => modes.includes(mode)) - .map(([mode, permission]) => permission) - } - return undefined - } - """ - * def getRequestData = - """ - function (type) { - switch(type) { - case 'rdf': - return { - contentType: 'text/turtle', - requestBody: '<> "Bob replaced it." .', - responseShouldNotContain: "Bob replaced it" - } - default: - return { - contentType: 'text/plain', - requestBody: "Bob's text", - responseShouldNotContain: "Bob's text" - } - } - } - """ - * def resourceEntry = - """ - function (container, type) { - switch (type) { - case 'plain': - return container.createResource('.txt', 'Hello', 'text/plain') - case 'fictive': - return container.reserveResource('.txt') - case 'rdf': - return container.createResource('.ttl', karate.readAsString('../fixtures/example.ttl'), 'text/turtle') - case 'container': - return container.createContainer() - default: - return undefined - } - } - """ - * def createResource = - """ - function (containerModes, resourceModes, resourceType, agent) { + * table resources + | type | container | resource | + | 'plain' | 'no' | 'WAC' | + | 'plain' | 'WAC' | 'inherited' | + | 'fictive' | 'WAC' | 'inherited' | + | 'rdf' | 'no' | 'WAC' | + | 'rdf' | 'WAC' | 'inherited' | + | 'container' | 'no' | 'WAC' | + | 'container' | 'WAC' | 'inherited' | + * def utils = callonce read('common.feature') ({resources, subject: 'agent', agent: webIds.bob}) - const agentWebId = webIds.bob - - const testContainerPermissions = resourcePermissions(containerModes == 'all' ? 'RWAC' : containerModes) - const testResourcePermissions = resourcePermissions(resourceModes) - - const testContainerInheritablePermissions = resourceModes == 'inherited' - ? testContainerPermissions - : resourceType == 'fictive' - ? testResourcePermissions - : undefined - - const testContainer = rootTestContainer.createContainer() - const testResource = resourceEntry(testContainer, resourceType) - - testContainer.accessDataset = testContainer.accessDatasetBuilder - .setAgentAccess(testContainer.url, agentWebId, testContainerPermissions) - .setInheritableAgentAccess(testContainer.url, agentWebId, testContainerInheritablePermissions) - .build() - - if (resourceType != 'fictive' && resourceModes != 'inherited') { - testResource.accessDataset = testResource.accessDatasetBuilder - .setAgentAccess(testResource.url, agentWebId, testResourcePermissions) - .build() - } - - return testResource - } - """ - - Scenario Outline: read a resource (), when an authenticated agent has access to the container and access to the resource - * def testResource = createResource(container, resource, type) + Scenario Outline: read a resource (), when Bob has access to the container and access to the resource + * def testResource = utils.getResource(container, resource, type) Given url testResource.url - And headers authHeaders(method, testResource.url, agent) + And headers utils.authHeaders(method, testResource.url, agent) When method Then status Examples: | agent | result | method | type | container | resource | status | - | Bob | cannot | GET | plain | no | AWC | 403 | - | Bob | cannot | GET | plain | AWC | inherited | 403 | - | Bob | cannot | GET | fictive | AWC | inherited | 403 | - | Bob | cannot | GET | rdf | no | AWC | 403 | - | Bob | cannot | GET | rdf | AWC | inherited | 403 | - | Bob | cannot | GET | container | no | AWC | 403 | - | Bob | cannot | GET | container | AWC | inherited | 403 | - | Bob | cannot | HEAD | plain | no | AWC | 403 | - | Bob | cannot | HEAD | plain | AWC | inherited | 403 | - | Bob | cannot | HEAD | fictive | AWC | inherited | 403 | - | Bob | cannot | HEAD | rdf | no | AWC | 403 | - | Bob | cannot | HEAD | rdf | AWC | inherited | 403 | - | Bob | cannot | HEAD | container | no | AWC | 403 | - | Bob | cannot | HEAD | container | AWC | inherited | 403 | - | Public | cannot | GET | plain | no | AWC | 401 | - | Public | cannot | GET | plain | AWC | inherited | 401 | - | Public | cannot | GET | fictive | AWC | inherited | 401 | - | Public | cannot | GET | rdf | no | AWC | 401 | - | Public | cannot | GET | rdf | AWC | inherited | 401 | - | Public | cannot | GET | container | no | AWC | 401 | - | Public | cannot | GET | container | AWC | inherited | 401 | - | Public | cannot | HEAD | plain | no | AWC | 401 | - | Public | cannot | HEAD | plain | AWC | inherited | 401 | - | Public | cannot | HEAD | fictive | AWC | inherited | 401 | - | Public | cannot | HEAD | rdf | no | AWC | 401 | - | Public | cannot | HEAD | rdf | AWC | inherited | 401 | - | Public | cannot | HEAD | container | no | AWC | 401 | - | Public | cannot | HEAD | container | AWC | inherited | 401 | + | Bob | cannot | GET | plain | no | WAC | 403 | + | Bob | cannot | GET | plain | WAC | inherited | 403 | + | Bob | cannot | GET | fictive | WAC | inherited | 403 | + | Bob | cannot | GET | rdf | no | WAC | 403 | + | Bob | cannot | GET | rdf | WAC | inherited | 403 | + | Bob | cannot | GET | container | no | WAC | 403 | + | Bob | cannot | GET | container | WAC | inherited | 403 | + | Bob | cannot | HEAD | plain | no | WAC | 403 | + | Bob | cannot | HEAD | plain | WAC | inherited | 403 | + | Bob | cannot | HEAD | fictive | WAC | inherited | 403 | + | Bob | cannot | HEAD | rdf | no | WAC | 403 | + | Bob | cannot | HEAD | rdf | WAC | inherited | 403 | + | Bob | cannot | HEAD | container | no | WAC | 403 | + | Bob | cannot | HEAD | container | WAC | inherited | 403 | + | Public | cannot | GET | plain | no | WAC | 401 | + | Public | cannot | GET | plain | WAC | inherited | 401 | + | Public | cannot | GET | fictive | WAC | inherited | 401 | + | Public | cannot | GET | rdf | no | WAC | 401 | + | Public | cannot | GET | rdf | WAC | inherited | 401 | + | Public | cannot | GET | container | no | WAC | 401 | + | Public | cannot | GET | container | WAC | inherited | 401 | + | Public | cannot | HEAD | plain | no | WAC | 401 | + | Public | cannot | HEAD | plain | WAC | inherited | 401 | + | Public | cannot | HEAD | fictive | WAC | inherited | 401 | + | Public | cannot | HEAD | rdf | no | WAC | 401 | + | Public | cannot | HEAD | rdf | WAC | inherited | 401 | + | Public | cannot | HEAD | container | no | WAC | 401 | + | Public | cannot | HEAD | container | WAC | inherited | 401 | - Scenario Outline: write a resource () and cannot read it, when an authenticated agent has access to the container and access to the resource - * def testResource = createResource(container, resource, type) - * def requestData = getRequestData(type) + Scenario Outline: write a resource () and cannot read it, when Bob has access to the container and access to the resource + * def testResource = utils.createResource(container, resource, type, 'agent', webIds.bob) + * def requestData = utils.getRequestData(type) Given url testResource.url - And headers authHeaders(method, testResource.url, agent) + And headers utils.authHeaders(method, testResource.url, agent) And header Content-Type = requestData.contentType And request requestData.requestBody When method @@ -140,7 +64,7 @@ Feature: Only Bob can write (and only that) a resource when granted write access And string responseString = response And match responseString !contains requestData.responseShouldNotContain - Given headers authHeaders('GET', testResource.url, agent) + Given headers utils.authHeaders('GET', testResource.url, agent) When method GET Then status @@ -163,19 +87,20 @@ Feature: Only Bob can write (and only that) a resource when granted write access | Public | cannot | POST | container | no | WAC | [401] | 401 | | Public | cannot | POST | container | WAC | inherited | [401] | 401 | - Scenario Outline: to a resource, when an authenticated agent has access to the container and access to the resource - * def testResource = createResource(container, resource, type) + Scenario Outline: to a resource, when Bob has access to the container and access to the resource + * def testResource = utils.createResource(container, resource, type, 'agent', webIds.bob) + * def requestData = utils.getRequestData('text/n3') Given url testResource.url - And headers authHeaders(method, testResource.url, agent) - And header Content-Type = 'text/n3' - And request '@prefix solid: . _:insert a solid:InsertDeletePatch; solid:inserts { <> a . }.' + And headers utils.authHeaders(method, testResource.url, agent) + And header Content-Type = requestData.contentType + And request requestData.requestBody When method Then match contains responseStatus # Server may return payload with information about the operation e.g. "Created" so check it hasn't leaked the data which was PUT And string responseString = response - And match responseString !contains 'http://example.org#Foo' + And match responseString !contains requestData.responseShouldNotContain - Given headers authHeaders('GET', testResource.url, agent) + Given headers utils.authHeaders('GET', testResource.url, agent) When method GET Then status @@ -194,39 +119,39 @@ Feature: Only Bob can write (and only that) a resource when granted write access | Public | cannot | PATCH | rdf | WAC | inherited | [401] | 401 | | Public | cannot | PATCH | fictive | WAC | inherited | [401] | 401 | - Scenario Outline: a resource, when an authenticated agent has access to the container and access to the resource - * def testResource = createResource(container, resource, type) + Scenario Outline: a resource, when Bob has access to the container and access to the resource + * def testResource = utils.createResource(container, resource, type, 'agent', webIds.bob) Given url testResource.url - And headers authHeaders(method, testResource.url, agent) + And headers utils.authHeaders(method, testResource.url, agent) When method - Then status + Then match contains responseStatus Examples: - | agent | result | method | type | container | resource | status | - | Bob | cannot | DELETE | plain | no | C | 403 | - | Bob | cannot | DELETE | plain | C | inherited | 403 | - | Bob | cannot | DELETE | fictive | C | inherited | 403 | - | Bob | cannot | DELETE | rdf | no | C | 403 | - | Bob | cannot | DELETE | rdf | C | inherited | 403 | - | Bob | cannot | DELETE | container | no | C | 403 | - | Bob | cannot | DELETE | container | C | inherited | 403 | - | Bob | cannot | DELETE | plain | no | A | 403 | - | Bob | cannot | DELETE | plain | A | inherited | 403 | - | Bob | cannot | DELETE | fictive | A | inherited | 403 | - | Bob | cannot | DELETE | rdf | no | A | 403 | - | Bob | cannot | DELETE | rdf | A | inherited | 403 | - | Bob | cannot | DELETE | container | no | A | 403 | - | Bob | cannot | DELETE | container | A | inherited | 403 | - | Bob | cannot | DELETE | plain | no | W | 403 | - | Bob | can | DELETE | plain | W | inherited | 205 | - | Bob | cannot | DELETE | fictive | W | inherited | 404 | - | Bob | cannot | DELETE | rdf | no | W | 403 | - | Bob | can | DELETE | rdf | W | inherited | 205 | - | Bob | cannot | DELETE | container | no | W | 403 | - | Bob | cannot | DELETE | container | W | inherited | 403 | - | Public | cannot | DELETE | plain | no | WAC | 401 | - | Public | cannot | DELETE | plain | WAC | inherited | 401 | - | Public | cannot | DELETE | fictive | WAC | inherited | 401 | - | Public | cannot | DELETE | rdf | no | WAC | 401 | - | Public | cannot | DELETE | rdf | WAC | inherited | 401 | - | Public | cannot | DELETE | container | no | WAC | 401 | - | Public | cannot | DELETE | container | WAC | inherited | 401 | + | agent | result | method | type | container | resource | status | + | Bob | cannot | DELETE | plain | no | C | [403] | + | Bob | cannot | DELETE | plain | C | inherited | [403] | + | Bob | cannot | DELETE | fictive | C | inherited | [403] | + | Bob | cannot | DELETE | rdf | no | C | [403] | + | Bob | cannot | DELETE | rdf | C | inherited | [403] | + | Bob | cannot | DELETE | container | no | C | [403] | + | Bob | cannot | DELETE | container | C | inherited | [403] | + | Bob | cannot | DELETE | plain | no | A | [403] | + | Bob | cannot | DELETE | plain | A | inherited | [403] | + | Bob | cannot | DELETE | fictive | A | inherited | [403] | + | Bob | cannot | DELETE | rdf | no | A | [403] | + | Bob | cannot | DELETE | rdf | A | inherited | [403] | + | Bob | cannot | DELETE | container | no | A | [403] | + | Bob | cannot | DELETE | container | A | inherited | [403] | + | Bob | cannot | DELETE | plain | no | W | [403] | + | Bob | can | DELETE | plain | W | inherited | [200, 202, 204, 205] | + | Bob | cannot | DELETE | fictive | W | inherited | [403] | + | Bob | cannot | DELETE | rdf | no | W | [403] | + | Bob | can | DELETE | rdf | W | inherited | [200, 202, 204, 205] | + | Bob | cannot | DELETE | container | no | W | [403] | + | Bob | cannot | DELETE | container | W | inherited | [403] | + | Public | cannot | DELETE | plain | no | WAC | [401] | + | Public | cannot | DELETE | plain | WAC | inherited | [401] | + | Public | cannot | DELETE | fictive | WAC | inherited | [401] | + | Public | cannot | DELETE | rdf | no | WAC | [401] | + | Public | cannot | DELETE | rdf | WAC | inherited | [401] | + | Public | cannot | DELETE | container | no | WAC | [401] | + | Public | cannot | DELETE | container | WAC | inherited | [401] | diff --git a/web-access-control/protected-operation/write-access-public.feature b/web-access-control/protected-operation/write-access-public.feature index cbadc50..2f08215 100644 --- a/web-access-control/protected-operation/write-access-public.feature +++ b/web-access-control/protected-operation/write-access-public.feature @@ -3,109 +3,43 @@ Feature: Only authenticated agents can write (and only that) a resource when gra # - restricted access or no access to the parent container # - restricted access to the test resources, or inherited access for fictive resources Background: Create test resources with correct access modes - * def resourcePermissions = - """ - function (modes) { - if (modes && modes != 'inherited' && modes != 'no') { - return Object.entries({ R: 'read', W: 'write', A: 'append', C: 'control' }) - .filter(([mode, permission]) => modes.includes(mode)) - .map(([mode, permission]) => permission) - } - return undefined - } - """ - * def getRequestData = - """ - function (type) { - switch(type) { - case 'rdf': - return { - contentType: 'text/turtle', - requestBody: '<> "Bob replaced it." .', - responseShouldNotContain: "Bob replaced it" - } - default: - return { - contentType: 'text/plain', - requestBody: "Bob's text", - responseShouldNotContain: "Bob's text" - } - } - } - """ - * def resourceEntry = - """ - function (container, type) { - switch (type) { - case 'plain': - return container.createResource('.txt', 'Hello', 'text/plain') - case 'fictive': - return container.reserveResource('.txt') - case 'rdf': - return container.createResource('.ttl', karate.readAsString('../fixtures/example.ttl'), 'text/turtle') - case 'container': - return container.createContainer() - default: - return undefined - } - } - """ - * def createResource = - """ - function (containerModes, resourceModes, resourceType) { + * table resources + | type | container | resource | + | 'plain' | 'no' | 'WAC' | + | 'plain' | 'WAC' | 'inherited' | + | 'fictive' | 'WAC' | 'inherited' | + | 'rdf' | 'no' | 'WAC' | + | 'rdf' | 'WAC' | 'inherited' | + | 'container' | 'no' | 'WAC' | + | 'container' | 'WAC' | 'inherited' | + * def utils = callonce read('common.feature') ({resources, subject: 'public'}) - const testContainerPermissions = resourcePermissions(containerModes == 'all' ? 'RWAC' : containerModes) - const testResourcePermissions = resourcePermissions(resourceModes) - - const testContainerInheritablePermissions = resourceModes == 'inherited' - ? testContainerPermissions - : resourceType == 'fictive' - ? testResourcePermissions - : undefined - - const testContainer = rootTestContainer.createContainer() - const testResource = resourceEntry(testContainer, resourceType) - - testContainer.accessDataset = testContainer.accessDatasetBuilder - .setPublicAccess(testContainer.url, testContainerPermissions) - .setInheritablePublicAccess(testContainer.url, testContainerInheritablePermissions) - .build() - - if (resourceType != 'fictive' && resourceModes != 'inherited') { - testResource.accessDataset = testResource.accessDatasetBuilder - .setPublicAccess(testResource.url, testResourcePermissions) - .build() - } - - return testResource - } - """ - - Scenario Outline: read a resource (), when an authenticated agent has access to the container and access to the resource - * def testResource = createResource(container, resource, type) + Scenario Outline: read a resource (), when a public agent has access to the container and access to the resource + * def testResource = utils.getResource(container, resource, type) Given url testResource.url When method Then status Examples: | agent | result | method | type | container | resource | status | - | Public | cannot | GET | plain | no | AWC | 401 | - | Public | cannot | GET | plain | AWC | inherited | 401 | - | Public | cannot | GET | fictive | AWC | inherited | 401 | - | Public | cannot | GET | rdf | no | AWC | 401 | - | Public | cannot | GET | rdf | AWC | inherited | 401 | - | Public | cannot | GET | container | no | AWC | 401 | - | Public | cannot | GET | container | AWC | inherited | 401 | - | Public | cannot | HEAD | plain | no | AWC | 401 | - | Public | cannot | HEAD | plain | AWC | inherited | 401 | - | Public | cannot | HEAD | fictive | AWC | inherited | 401 | - | Public | cannot | HEAD | rdf | no | AWC | 401 | - | Public | cannot | HEAD | rdf | AWC | inherited | 401 | - | Public | cannot | HEAD | container | no | AWC | 401 | - | Public | cannot | HEAD | container | AWC | inherited | 401 | + | Public | cannot | GET | plain | no | WAC | 401 | + | Public | cannot | GET | plain | WAC | inherited | 401 | + | Public | cannot | GET | fictive | WAC | inherited | 401 | + | Public | cannot | GET | rdf | no | WAC | 401 | + | Public | cannot | GET | rdf | WAC | inherited | 401 | + | Public | cannot | GET | container | no | WAC | 401 | + | Public | cannot | GET | container | WAC | inherited | 401 | + | Public | cannot | HEAD | plain | no | WAC | 401 | + | Public | cannot | HEAD | plain | WAC | inherited | 401 | + | Public | cannot | HEAD | fictive | WAC | inherited | 401 | + | Public | cannot | HEAD | rdf | no | WAC | 401 | + | Public | cannot | HEAD | rdf | WAC | inherited | 401 | + | Public | cannot | HEAD | container | no | WAC | 401 | + | Public | cannot | HEAD | container | WAC | inherited | 401 | - Scenario Outline: write a resource () and cannot read it, when an authenticated agent has access to the container and access to the resource - * def testResource = createResource(container, resource, type) - * def requestData = getRequestData(type) + @publicagent + Scenario Outline: write a resource () and cannot read it, when a public agent has access to the container and access to the resource + * def testResource = utils.createResource(container, resource, type, 'public') + * def requestData = utils.getRequestData(type) Given url testResource.url And header Content-Type = requestData.contentType And request requestData.requestBody @@ -130,16 +64,18 @@ Feature: Only authenticated agents can write (and only that) a resource when gra | Public | can | POST | container | no | A | [201, 204, 205] | 401 | | Public | can | POST | container | A | inherited | [201, 204, 205] | 401 | - Scenario Outline: to a resource, when an authenticated agent has access to the container and access to the resource - * def testResource = createResource(container, resource, type) + @publicagent + Scenario Outline: to a resource, when a public agent has access to the container and access to the resource + * def testResource = utils.createResource(container, resource, type, 'public') + * def requestData = utils.getRequestData('text/n3') Given url testResource.url - And header Content-Type = 'text/n3' - And request '@prefix solid: . _:insert a solid:InsertDeletePatch; solid:inserts { <> a . }.' + And header Content-Type = requestData.contentType + And request requestData.requestBody When method Then match contains responseStatus # Server may return payload with information about the operation e.g. "Created" so check it hasn't leaked the data which was PUT And string responseString = response - And match responseString !contains 'http://example.org#Foo' + And match responseString !contains requestData.responseShouldNotContain When method GET Then status @@ -156,31 +92,32 @@ Feature: Only authenticated agents can write (and only that) a resource when gra | Public | cannot | PATCH | rdf | C | inherited | [401] | 401 | | Public | cannot | PATCH | fictive | C | inherited | [401] | 401 | - Scenario Outline: a resource, when an authenticated agent has access to the container and access to the resource - * def testResource = createResource(container, resource, type) + @publicagent + Scenario Outline: a resource, when a public agent has access to the container and access to the resource + * def testResource = utils.createResource(container, resource, type, 'public') Given url testResource.url When method - Then status + Then match contains responseStatus Examples: - | agent | result | method | type | container | resource | status | - | Public | cannot | DELETE | plain | no | C | 401 | - | Public | cannot | DELETE | plain | C | inherited | 401 | - | Public | cannot | DELETE | fictive | C | inherited | 401 | - | Public | cannot | DELETE | rdf | no | C | 401 | - | Public | cannot | DELETE | rdf | C | inherited | 401 | - | Public | cannot | DELETE | container | no | C | 401 | - | Public | cannot | DELETE | container | C | inherited | 401 | - | Public | cannot | DELETE | plain | no | A | 401 | - | Public | cannot | DELETE | plain | A | inherited | 401 | - | Public | cannot | DELETE | fictive | A | inherited | 401 | - | Public | cannot | DELETE | rdf | no | A | 401 | - | Public | cannot | DELETE | rdf | A | inherited | 401 | - | Public | cannot | DELETE | container | no | A | 401 | - | Public | cannot | DELETE | container | A | inherited | 401 | - | Public | cannot | DELETE | plain | no | W | 401 | - | Public | can | DELETE | plain | W | inherited | 205 | - | Public | cannot | DELETE | fictive | W | inherited | 404 | - | Public | cannot | DELETE | rdf | no | W | 401 | - | Public | can | DELETE | rdf | W | inherited | 205 | - | Public | cannot | DELETE | container | no | W | 401 | - | Public | cannot | DELETE | container | W | inherited | 401 | + | agent | result | method | type | container | resource | status | + | Public | cannot | DELETE | plain | no | C | [401] | + | Public | cannot | DELETE | plain | C | inherited | [401] | + | Public | cannot | DELETE | fictive | C | inherited | [401] | + | Public | cannot | DELETE | rdf | no | C | [401] | + | Public | cannot | DELETE | rdf | C | inherited | [401] | + | Public | cannot | DELETE | container | no | C | [401] | + | Public | cannot | DELETE | container | C | inherited | [401] | + | Public | cannot | DELETE | plain | no | A | [401] | + | Public | cannot | DELETE | plain | A | inherited | [401] | + | Public | cannot | DELETE | fictive | A | inherited | [401] | + | Public | cannot | DELETE | rdf | no | A | [401] | + | Public | cannot | DELETE | rdf | A | inherited | [401] | + | Public | cannot | DELETE | container | no | A | [401] | + | Public | cannot | DELETE | container | A | inherited | [401] | + | Public | cannot | DELETE | plain | no | W | [401] | + | Public | can | DELETE | plain | W | inherited | [200, 202, 204, 205] | + | Public | cannot | DELETE | fictive | W | inherited | [401] | + | Public | cannot | DELETE | rdf | no | W | [401] | + | Public | can | DELETE | rdf | W | inherited | [200, 202, 204, 205] | + | Public | cannot | DELETE | container | no | W | [401] | + | Public | cannot | DELETE | container | W | inherited | [401] | From 02aa550c0d392d579ce19ad0a0775908663e100a Mon Sep 17 00:00:00 2001 From: Pete Edwards Date: Thu, 13 Oct 2022 11:51:22 +0100 Subject: [PATCH 8/8] Allow 200 responses, restrict to 201 for PUT to create, remove redundant test --- .../write-access-agent.feature | 60 +++++++++---------- .../write-access-bob.feature | 60 +++++++++---------- .../write-access-public.feature | 40 ++++++------- .../write-without-read.feature | 41 ------------- .../web-access-control-test-manifest.ttl | 7 --- 5 files changed, 80 insertions(+), 128 deletions(-) delete mode 100644 web-access-control/protected-operation/write-without-read.feature diff --git a/web-access-control/protected-operation/write-access-agent.feature b/web-access-control/protected-operation/write-access-agent.feature index 346a918..0d78bdd 100644 --- a/web-access-control/protected-operation/write-access-agent.feature +++ b/web-access-control/protected-operation/write-access-agent.feature @@ -69,23 +69,23 @@ Feature: Only authenticated agents can write (and only that) a resource when gra Then status Examples: - | agent | result | method | type | container | resource | writeStatus | readStatus | - | Bob | can | PUT | rdf | no | W | [201, 204, 205] | 403 | - | Bob | can | PUT | rdf | W | inherited | [201, 204, 205] | 403 | - | Bob | can | PUT | plain | no | W | [201, 204, 205] | 403 | - | Bob | can | PUT | plain | W | inherited | [201, 204, 205] | 403 | - | Bob | can | PUT | fictive | W | inherited | [201, 204, 205] | 403 | - | Bob | can | POST | container | no | W | [201, 204, 205] | 403 | - | Bob | can | POST | container | W | inherited | [201, 204, 205] | 403 | - | Bob | can | POST | container | no | A | [201, 204, 205] | 403 | - | Bob | can | POST | container | A | inherited | [201, 204, 205] | 403 | - | Public | cannot | PUT | rdf | no | WAC | [401] | 401 | - | Public | cannot | PUT | rdf | WAC | inherited | [401] | 401 | - | Public | cannot | PUT | plain | no | WAC | [401] | 401 | - | Public | cannot | PUT | plain | WAC | inherited | [401] | 401 | - | Public | cannot | PUT | fictive | WAC | inherited | [401] | 401 | - | Public | cannot | POST | container | no | WAC | [401] | 401 | - | Public | cannot | POST | container | WAC | inherited | [401] | 401 | + | agent | result | method | type | container | resource | writeStatus | readStatus | + | Bob | can | PUT | rdf | no | W | [200, 201, 204, 205] | 403 | + | Bob | can | PUT | rdf | W | inherited | [200, 201, 204, 205] | 403 | + | Bob | can | PUT | plain | no | W | [200, 201, 204, 205] | 403 | + | Bob | can | PUT | plain | W | inherited | [200, 201, 204, 205] | 403 | + | Bob | can | PUT | fictive | W | inherited | [201] | 403 | + | Bob | can | POST | container | no | W | [200, 201, 204, 205] | 403 | + | Bob | can | POST | container | W | inherited | [200, 201, 204, 205] | 403 | + | Bob | can | POST | container | no | A | [200, 201, 204, 205] | 403 | + | Bob | can | POST | container | A | inherited | [200, 201, 204, 205] | 403 | + | Public | cannot | PUT | rdf | no | WAC | [401] | 401 | + | Public | cannot | PUT | rdf | WAC | inherited | [401] | 401 | + | Public | cannot | PUT | plain | no | WAC | [401] | 401 | + | Public | cannot | PUT | plain | WAC | inherited | [401] | 401 | + | Public | cannot | PUT | fictive | WAC | inherited | [401] | 401 | + | Public | cannot | POST | container | no | WAC | [401] | 401 | + | Public | cannot | POST | container | WAC | inherited | [401] | 401 | Scenario Outline: to a resource, when an authenticated agent has access to the container and access to the resource * def testResource = utils.createResource(container, resource, type, 'authenticated') @@ -105,19 +105,19 @@ Feature: Only authenticated agents can write (and only that) a resource when gra Then status Examples: - | agent | result | method | type | container | resource | writeStatus | readStatus | - | Bob | can | PATCH | rdf | no | W | [201, 204, 205] | 403 | - | Bob | can | PATCH | rdf | W | inherited | [201, 204, 205] | 403 | - | Bob | can | PATCH | fictive | W | inherited | [201, 204, 205] | 403 | - | Bob | can | PATCH | rdf | no | A | [201, 204, 205] | 403 | - | Bob | can | PATCH | rdf | A | inherited | [201, 204, 205] | 403 | - | Bob | can | PATCH | fictive | A | inherited | [201, 204, 205] | 403 | - | Bob | cannot | PATCH | rdf | no | C | [403] | 403 | - | Bob | cannot | PATCH | rdf | C | inherited | [403] | 403 | - | Bob | cannot | PATCH | fictive | C | inherited | [403] | 403 | - | Public | cannot | PATCH | rdf | no | WAC | [401] | 401 | - | Public | cannot | PATCH | rdf | WAC | inherited | [401] | 401 | - | Public | cannot | PATCH | fictive | WAC | inherited | [401] | 401 | + | agent | result | method | type | container | resource | writeStatus | readStatus | + | Bob | can | PATCH | rdf | no | W | [200, 201, 204, 205] | 403 | + | Bob | can | PATCH | rdf | W | inherited | [200, 201, 204, 205] | 403 | + | Bob | can | PATCH | fictive | W | inherited | [200, 201, 204, 205] | 403 | + | Bob | can | PATCH | rdf | no | A | [200, 201, 204, 205] | 403 | + | Bob | can | PATCH | rdf | A | inherited | [200, 201, 204, 205] | 403 | + | Bob | can | PATCH | fictive | A | inherited | [200, 201, 204, 205] | 403 | + | Bob | cannot | PATCH | rdf | no | C | [403] | 403 | + | Bob | cannot | PATCH | rdf | C | inherited | [403] | 403 | + | Bob | cannot | PATCH | fictive | C | inherited | [403] | 403 | + | Public | cannot | PATCH | rdf | no | WAC | [401] | 401 | + | Public | cannot | PATCH | rdf | WAC | inherited | [401] | 401 | + | Public | cannot | PATCH | fictive | WAC | inherited | [401] | 401 | Scenario Outline: a resource, when an authenticated agent has access to the container and access to the resource * def testResource = utils.createResource(container, resource, type, 'authenticated') diff --git a/web-access-control/protected-operation/write-access-bob.feature b/web-access-control/protected-operation/write-access-bob.feature index 511917f..acab04f 100644 --- a/web-access-control/protected-operation/write-access-bob.feature +++ b/web-access-control/protected-operation/write-access-bob.feature @@ -69,23 +69,23 @@ Feature: Only Bob can write (and only that) a resource when granted write access Then status Examples: - | agent | result | method | type | container | resource | writeStatus | readStatus | - | Bob | can | PUT | rdf | no | W | [201, 204, 205] | 403 | - | Bob | can | PUT | rdf | W | inherited | [201, 204, 205] | 403 | - | Bob | can | PUT | plain | no | W | [201, 204, 205] | 403 | - | Bob | can | PUT | plain | W | inherited | [201, 204, 205] | 403 | - | Bob | can | PUT | fictive | W | inherited | [201, 204, 205] | 403 | - | Bob | can | POST | container | no | W | [201, 204, 205] | 403 | - | Bob | can | POST | container | W | inherited | [201, 204, 205] | 403 | - | Bob | can | POST | container | no | A | [201, 204, 205] | 403 | - | Bob | can | POST | container | A | inherited | [201, 204, 205] | 403 | - | Public | cannot | PUT | rdf | no | WAC | [401] | 401 | - | Public | cannot | PUT | rdf | WAC | inherited | [401] | 401 | - | Public | cannot | PUT | plain | no | WAC | [401] | 401 | - | Public | cannot | PUT | plain | WAC | inherited | [401] | 401 | - | Public | cannot | PUT | fictive | WAC | inherited | [401] | 401 | - | Public | cannot | POST | container | no | WAC | [401] | 401 | - | Public | cannot | POST | container | WAC | inherited | [401] | 401 | + | agent | result | method | type | container | resource | writeStatus | readStatus | + | Bob | can | PUT | rdf | no | W | [200, 201, 204, 205] | 403 | + | Bob | can | PUT | rdf | W | inherited | [200, 201, 204, 205] | 403 | + | Bob | can | PUT | plain | no | W | [200, 201, 204, 205] | 403 | + | Bob | can | PUT | plain | W | inherited | [200, 201, 204, 205] | 403 | + | Bob | can | PUT | fictive | W | inherited | [201] | 403 | + | Bob | can | POST | container | no | W | [200, 201, 204, 205] | 403 | + | Bob | can | POST | container | W | inherited | [200, 201, 204, 205] | 403 | + | Bob | can | POST | container | no | A | [200, 201, 204, 205] | 403 | + | Bob | can | POST | container | A | inherited | [200, 201, 204, 205] | 403 | + | Public | cannot | PUT | rdf | no | WAC | [401] | 401 | + | Public | cannot | PUT | rdf | WAC | inherited | [401] | 401 | + | Public | cannot | PUT | plain | no | WAC | [401] | 401 | + | Public | cannot | PUT | plain | WAC | inherited | [401] | 401 | + | Public | cannot | PUT | fictive | WAC | inherited | [401] | 401 | + | Public | cannot | POST | container | no | WAC | [401] | 401 | + | Public | cannot | POST | container | WAC | inherited | [401] | 401 | Scenario Outline: to a resource, when Bob has access to the container and access to the resource * def testResource = utils.createResource(container, resource, type, 'agent', webIds.bob) @@ -105,19 +105,19 @@ Feature: Only Bob can write (and only that) a resource when granted write access Then status Examples: - | agent | result | method | type | container | resource | writeStatus | readStatus | - | Bob | can | PATCH | rdf | no | W | [201, 204, 205] | 403 | - | Bob | can | PATCH | rdf | W | inherited | [201, 204, 205] | 403 | - | Bob | can | PATCH | fictive | W | inherited | [201, 204, 205] | 403 | - | Bob | can | PATCH | rdf | no | A | [201, 204, 205] | 403 | - | Bob | can | PATCH | rdf | A | inherited | [201, 204, 205] | 403 | - | Bob | can | PATCH | fictive | A | inherited | [201, 204, 205] | 403 | - | Bob | cannot | PATCH | rdf | no | C | [403] | 403 | - | Bob | cannot | PATCH | rdf | C | inherited | [403] | 403 | - | Bob | cannot | PATCH | fictive | C | inherited | [403] | 403 | - | Public | cannot | PATCH | rdf | no | WAC | [401] | 401 | - | Public | cannot | PATCH | rdf | WAC | inherited | [401] | 401 | - | Public | cannot | PATCH | fictive | WAC | inherited | [401] | 401 | + | agent | result | method | type | container | resource | writeStatus | readStatus | + | Bob | can | PATCH | rdf | no | W | [200, 201, 204, 205] | 403 | + | Bob | can | PATCH | rdf | W | inherited | [200, 201, 204, 205] | 403 | + | Bob | can | PATCH | fictive | W | inherited | [200, 201, 204, 205] | 403 | + | Bob | can | PATCH | rdf | no | A | [200, 201, 204, 205] | 403 | + | Bob | can | PATCH | rdf | A | inherited | [200, 201, 204, 205] | 403 | + | Bob | can | PATCH | fictive | A | inherited | [200, 201, 204, 205] | 403 | + | Bob | cannot | PATCH | rdf | no | C | [403] | 403 | + | Bob | cannot | PATCH | rdf | C | inherited | [403] | 403 | + | Bob | cannot | PATCH | fictive | C | inherited | [403] | 403 | + | Public | cannot | PATCH | rdf | no | WAC | [401] | 401 | + | Public | cannot | PATCH | rdf | WAC | inherited | [401] | 401 | + | Public | cannot | PATCH | fictive | WAC | inherited | [401] | 401 | Scenario Outline: a resource, when Bob has access to the container and access to the resource * def testResource = utils.createResource(container, resource, type, 'agent', webIds.bob) diff --git a/web-access-control/protected-operation/write-access-public.feature b/web-access-control/protected-operation/write-access-public.feature index 2f08215..0ed4308 100644 --- a/web-access-control/protected-operation/write-access-public.feature +++ b/web-access-control/protected-operation/write-access-public.feature @@ -53,16 +53,16 @@ Feature: Only authenticated agents can write (and only that) a resource when gra Then status Examples: - | agent | result | method | type | container | resource | writeStatus | readStatus | - | Public | can | PUT | rdf | no | W | [201, 204, 205] | 401 | - | Public | can | PUT | rdf | W | inherited | [201, 204, 205] | 401 | - | Public | can | PUT | plain | no | W | [201, 204, 205] | 401 | - | Public | can | PUT | plain | W | inherited | [201, 204, 205] | 401 | - | Public | can | PUT | fictive | W | inherited | [201, 204, 205] | 401 | - | Public | can | POST | container | no | W | [201, 204, 205] | 401 | - | Public | can | POST | container | W | inherited | [201, 204, 205] | 401 | - | Public | can | POST | container | no | A | [201, 204, 205] | 401 | - | Public | can | POST | container | A | inherited | [201, 204, 205] | 401 | + | agent | result | method | type | container | resource | writeStatus | readStatus | + | Public | can | PUT | rdf | no | W | [200, 201, 204, 205] | 401 | + | Public | can | PUT | rdf | W | inherited | [200, 201, 204, 205] | 401 | + | Public | can | PUT | plain | no | W | [200, 201, 204, 205] | 401 | + | Public | can | PUT | plain | W | inherited | [200, 201, 204, 205] | 401 | + | Public | can | PUT | fictive | W | inherited | [201] | 401 | + | Public | can | POST | container | no | W | [200, 201, 204, 205] | 401 | + | Public | can | POST | container | W | inherited | [200, 201, 204, 205] | 401 | + | Public | can | POST | container | no | A | [200, 201, 204, 205] | 401 | + | Public | can | POST | container | A | inherited | [200, 201, 204, 205] | 401 | @publicagent Scenario Outline: to a resource, when a public agent has access to the container and access to the resource @@ -81,16 +81,16 @@ Feature: Only authenticated agents can write (and only that) a resource when gra Then status Examples: - | agent | result | method | type | container | resource | writeStatus | readStatus | - | Public | can | PATCH | rdf | no | W | [201, 204, 205] | 401 | - | Public | can | PATCH | rdf | W | inherited | [201, 204, 205] | 401 | - | Public | can | PATCH | fictive | W | inherited | [201, 204, 205] | 401 | - | Public | can | PATCH | rdf | no | A | [201, 204, 205] | 401 | - | Public | can | PATCH | rdf | A | inherited | [201, 204, 205] | 401 | - | Public | can | PATCH | fictive | A | inherited | [201, 204, 205] | 401 | - | Public | cannot | PATCH | rdf | no | C | [401] | 401 | - | Public | cannot | PATCH | rdf | C | inherited | [401] | 401 | - | Public | cannot | PATCH | fictive | C | inherited | [401] | 401 | + | agent | result | method | type | container | resource | writeStatus | readStatus | + | Public | can | PATCH | rdf | no | W | [200, 201, 204, 205] | 401 | + | Public | can | PATCH | rdf | W | inherited | [200, 201, 204, 205] | 401 | + | Public | can | PATCH | fictive | W | inherited | [200, 201, 204, 205] | 401 | + | Public | can | PATCH | rdf | no | A | [200, 201, 204, 205] | 401 | + | Public | can | PATCH | rdf | A | inherited | [200, 201, 204, 205] | 401 | + | Public | can | PATCH | fictive | A | inherited | [200, 201, 204, 205] | 401 | + | Public | cannot | PATCH | rdf | no | C | [401] | 401 | + | Public | cannot | PATCH | rdf | C | inherited | [401] | 401 | + | Public | cannot | PATCH | fictive | C | inherited | [401] | 401 | @publicagent Scenario Outline: a resource, when a public agent has access to the container and access to the resource diff --git a/web-access-control/protected-operation/write-without-read.feature b/web-access-control/protected-operation/write-without-read.feature deleted file mode 100644 index 2353b70..0000000 --- a/web-access-control/protected-operation/write-without-read.feature +++ /dev/null @@ -1,41 +0,0 @@ -# This test will move to the write operations group when added but represents a useful test to keep until then. -Feature: Bob cannot read an RDF resource even if he can write to it - - Background: Create test resource with all default access except read for Bob - * def setup = - """ - function() { - const testContainer = rootTestContainer.createContainer(); - const access = testContainer.accessDatasetBuilder - .setAgentAccess(testContainer.url, webIds.bob, ['write']) - .setInheritableAgentAccess(testContainer.url, webIds.bob, ['append', 'write', 'control']) - .build(); - testContainer.accessDataset = access; - return testContainer.createResource('.ttl', karate.readAsString('../fixtures/example.ttl'), 'text/turtle'); - } - """ - * def resource = callonce setup - * url resource.url - - Scenario: Bob cannot read the resource with GET - Given headers clients.bob.getAuthHeaders('GET', resource.url) - When method GET - Then status 403 - - Scenario: Bob cannot read the resource with HEAD - Given headers clients.bob.getAuthHeaders('HEAD', resource.url) - When method HEAD - Then status 403 - - Scenario: Bob can PUT to the resource but doesn't get it back since he cannot read - Given request '<> "Bob replaced it." .' - And headers clients.bob.getAuthHeaders('PUT', resource.url) - And header Content-Type = 'text/turtle' - When method PUT - Then match [201, 204, 205] contains responseStatus - # Server may return payload with information about the operation e.g. "Created" so check it hasn't leaked the data which was PUT - And match response !contains "Bob replaced it" - - Given headers clients.bob.getAuthHeaders('GET', resource.url) - When method GET - Then status 403 diff --git a/web-access-control/web-access-control-test-manifest.ttl b/web-access-control/web-access-control-test-manifest.ttl index 7876613..92176b6 100644 --- a/web-access-control/web-access-control-test-manifest.ttl +++ b/web-access-control/web-access-control-test-manifest.ttl @@ -48,13 +48,6 @@ manifest:protected-operation-acl-propagation spec:testScript . -manifest:protected-operation-write-without-read - a td:TestCase ; - spec:requirementReference wac:access-modes ; - td:reviewStatus td:unreviewed ; - spec:testScript - . - manifest:server-wac-allow-header-exists a td:TestCase ; spec:requirementReference wac:server-wac-allow ;