Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: return a DeletedResource or DeletedValue instead of 404 if a deleted resource or value is requested (DEV-226) #1960

Merged
merged 35 commits into from Jan 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
439a441
feat: add DeletedValue and DeletedResource to base ontology; see how …
BalduinLandolt Dec 6, 2021
169bb0a
feat: return DeletedResource for deleted resources
BalduinLandolt Dec 7, 2021
f6ad406
Merge branch 'main' into wip/DEV-226-show-deleted-resources
BalduinLandolt Dec 7, 2021
4a77b94
chore: update test data
BalduinLandolt Dec 7, 2021
e331933
refactor: move toDeletedResource to message; feat: add deleted resour…
BalduinLandolt Dec 9, 2021
00688a1
chore: update client-test-data
BalduinLandolt Dec 9, 2021
c4b8682
feat: implement DeletedValue
BalduinLandolt Dec 9, 2021
dc10b92
fix: version history can be retrieved even if a value was deleted
BalduinLandolt Dec 9, 2021
7d71a50
refactor: string interpolation issues
BalduinLandolt Dec 13, 2021
8da7c17
feast: correctly handle DeletedValue in resource history
BalduinLandolt Dec 13, 2021
e4d69b0
chore: update test data
BalduinLandolt Dec 13, 2021
61205cb
Merge branch 'main' into wip/DEV-226-show-deleted-resources
BalduinLandolt Dec 13, 2021
cc0b0f0
refactor: get rid of some code smells
BalduinLandolt Dec 13, 2021
1549035
refactor: remove additional code smell
BalduinLandolt Dec 13, 2021
52b0975
test: improve tests for deleted resources
BalduinLandolt Dec 13, 2021
140a9e9
docs: add docstrings
BalduinLandolt Dec 13, 2021
87eb1cb
Update ValuesResponderV2Spec.scala
BalduinLandolt Dec 13, 2021
61bff1a
Merge branch 'main' into wip/DEV-226-show-deleted-resources
BalduinLandolt Dec 14, 2021
84eb73b
docs: change codeblock language tag from jsonld to json
BalduinLandolt Dec 14, 2021
2a5e067
docs: add documentation for deleted resource
BalduinLandolt Dec 14, 2021
7f86d2b
fix: actually return deleted values
BalduinLandolt Dec 16, 2021
23ddd56
Merge branch 'main' into wip/DEV-226-show-deleted-resources
BalduinLandolt Dec 16, 2021
3931c39
refactor: remove codesmell
BalduinLandolt Dec 16, 2021
98c4b3a
docs: document DeletedValue
BalduinLandolt Dec 16, 2021
432e5ed
chore: update test data
BalduinLandolt Dec 17, 2021
e3dfaa1
Merge branch 'main' into wip/DEV-226-show-deleted-resources
BalduinLandolt Dec 17, 2021
4e50a15
docs: rectify documentation on DeletedValue
BalduinLandolt Dec 17, 2021
a20eed7
fix: correctly check if LinkValue was deleted
BalduinLandolt Dec 17, 2021
a6c734c
Merge branch 'main' into wip/DEV-226-show-deleted-resources
BalduinLandolt Dec 17, 2021
88764bd
Merge branch 'main' into wip/DEV-226-show-deleted-resources
BalduinLandolt Jan 3, 2022
0640a2b
docs: fix typos according to review
BalduinLandolt Jan 3, 2022
531db06
docs: apply changes according to review
BalduinLandolt Jan 3, 2022
e62cac5
docs: make snippets in docs valid JSON
BalduinLandolt Jan 3, 2022
3ff924f
refactor: rename some unclearly named variables
BalduinLandolt Jan 3, 2022
f266e33
Merge branch 'wip/DEV-226-show-deleted-resources' of https://github.c…
BalduinLandolt Jan 3, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
193 changes: 117 additions & 76 deletions docs/03-apis/api-v2/editing-resources.md
Expand Up @@ -14,15 +14,15 @@ HTTP POST to http://host/v2/resources
```

The body of the request is a JSON-LD document in the
[complex API schema](introduction.md#api-schema), specifying the type,`rdfs:label`, and its Knora resource properties and their values. The representation of the
resource is the same as when it is returned in a `GET` request, except that its `knora-api:attachedToUser` is not given,
and the resource IRI and those of its values can be optionally specified. The format of the values submitted
is described in [Editing Values](editing-values.md). If there are multiple values for a property,
these must be given in an array.
[complex API schema](introduction.md#api-schema), specifying the type,`rdfs:label`, and its Knora resource properties
and their values. The representation of the resource is the same as when it is returned in a `GET` request, except that
its `knora-api:attachedToUser` is not given, and the resource IRI and those of its values can be optionally specified.
The format of the values submitted is described in [Editing Values](editing-values.md). If there are multiple values for
a property, these must be given in an array.

For example, here is a request to create a resource with various value types:

```jsonld
```json
{
"@type" : "anything:Thing",
"anything:hasBoolean" : {
Expand Down Expand Up @@ -120,12 +120,12 @@ For example, here is a request to create a resource with various value types:
}
```

Permissions for the new resource can be given by adding `knora-api:hasPermissions`, a custom creation date
can be specified by adding `knora-api:creationDate`
(an [xsd:dateTimeStamp](https://www.w3.org/TR/xmlschema11-2/#dateTimeStamp)), and the
resource's creator can be specfied by adding `knora-api:attachedToUser`. For example:
Permissions for the new resource can be given by adding `knora-api:hasPermissions`, a custom creation date can be
specified by adding `knora-api:creationDate`
(an [xsd:dateTimeStamp](https://www.w3.org/TR/xmlschema11-2/#dateTimeStamp)), and the resource's creator can be specfied
by adding `knora-api:attachedToUser`. For example:

```jsonld
```json
{
"@type" : "anything:Thing",
"anything:hasBoolean" : {
Expand Down Expand Up @@ -157,36 +157,34 @@ resource's creator can be specfied by adding `knora-api:attachedToUser`. For exa
The format of the object of `knora-api:hasPermissions` is described in
[Permissions](../../02-knora-ontologies/knora-base.md#permissions).

If permissions are not given, configurable default permissions are used
(see [Default Object Access Permissions](../../05-internals/design/api-admin/administration.md#default-object-access-permissions)).
If permissions are not given, configurable default permissions are used (see
[Default Object Access Permissions](../../05-internals/design/api-admin/administration.md#default-object-access-permissions)
).

To create a resource, the user must have permission to create resources
of that class in that project.
To create a resource, the user must have permission to create resources of that class in that project.

The predicate `knora-api:attachedToUser` can be used to specify a creator other
than the requesting user only if the requesting user is an administrator of the
project or a system administrator. The specified creator must also
have permission to create resources of that class in that project.
The predicate `knora-api:attachedToUser` can be used to specify a creator other than the requesting user only if the
requesting user is an administrator of the project or a system administrator. The specified creator must also have
permission to create resources of that class in that project.

In addition to the creation date, in the body of the request, it is possible to specify a custom IRI (of [Knora IRI](knora-iris.md#iris-for-data) form) for a resource through
the `@id` attribute which will then be assigned to the resource; otherwise the resource will get a unique random IRI.
In addition to the creation date, in the body of the request, it is possible to specify a custom IRI (
of [Knora IRI](knora-iris.md#iris-for-data) form) for a resource through the `@id` attribute which will then be assigned
to the resource; otherwise the resource will get a unique random IRI.
BalduinLandolt marked this conversation as resolved.
Show resolved Hide resolved

A custom resource IRI must be `http://rdfh.ch/PROJECT_SHORTCODE/` (where `PROJECT_SHORTCODE`
is the shortcode of the project that the resource belongs to), plus a custom ID string.
is the shortcode of the project that the resource belongs to) plus a custom ID string.

Similarly, it is possible to assign a custom IRI to the values using their `@id` attributes; if not given, random IRIs
will be assigned to the values.

A custom value IRI must be the IRI of the containing resource, followed
by a `/values/` and a custom ID string.
A custom value IRI must be the IRI of the containing resource, followed by a `/values/` and a custom ID string.

An optional custom UUID of a value can also be given by adding `knora-api:valueHasUUID`.
Each custom UUID must be [base64url-encoded](https://tools.ietf.org/html/rfc4648#section-5), without padding. Each value of the new resource
can also have a custom creation date specified by adding `knora-api:creationDate`
(an [xsd:dateTimeStamp](https://www.w3.org/TR/xmlschema11-2/#dateTimeStamp)).
For example:
An optional custom UUID of a value can also be given by adding `knora-api:valueHasUUID`. Each custom UUID must
be [base64url-encoded](https://tools.ietf.org/html/rfc4648#section-5) without padding. Each value of the new resource
can also have a custom creation date specified by adding `knora-api:creationDate`
(an [xsd:dateTimeStamp](https://www.w3.org/TR/xmlschema11-2/#dateTimeStamp)). For example:

```jsonld
```json
{
"@id" : "http://rdfh.ch/0001/oveR1dQltEUwNrls9Lu5Rw",
"@type" : "anything:Thing",
Expand Down Expand Up @@ -217,7 +215,7 @@ For example:
}
}
```

The response is a JSON-LD document containing a
[preview](reading-and-searching-resources.md#get-the-preview-of-a-resource-by-iri)
of the resource.
Expand All @@ -244,17 +242,21 @@ The request body is a JSON-LD object containing the following information about

- `@id`: the resource's IRI
- `@type`: the resource's class IRI
- `knora-api:lastModificationDate`: an `xsd:dateTimeStamp` representing the last modification date that is currently attached to the resource, if any. This is used to make sure that the resource has not been modified by someone else since you last read it.
- `knora-api:lastModificationDate`: an `xsd:dateTimeStamp` representing the last modification date that is currently
attached to the resource, if any. This is used to make sure that the resource has not been modified by someone else
since you last read it.

The submitted JSON-LD object must also contain one or more of the following predicates, representing the metadata you want to change:
The submitted JSON-LD object must also contain one or more of the following predicates, representing the metadata you
want to change:

- `rdfs:label`: a string
- `knora-api:hasPermissions`, in the format described in [Permissions](../../02-knora-ontologies/knora-base.md#permissions)
- `knora-api:hasPermissions`, in the format described
in [Permissions](../../02-knora-ontologies/knora-base.md#permissions)
- `knora-api:newModificationDate`: an [xsd:dateTimeStamp](https://www.w3.org/TR/xmlschema11-2/#dateTimeStamp).

Here is an example:

```jsonld
```json
{
"@id" : "http://rdfh.ch/0001/a-thing",
"@type" : "anything:Thing",
Expand All @@ -278,8 +280,8 @@ Here is an example:
}
```

If you submit a `knora-api:lastModificationDate` that is different from the resource's actual last modification
date, you will get an HTTP 409 (Conflict) error.
If you submit a `knora-api:lastModificationDate` that is different from the resource's actual last modification date,
you will get an HTTP 409 (Conflict) error.

If you submit a `knora-api:newModificationDate` that is earlier than the resource's `knora-api:lastModificationDate`,
you will get an HTTP 400 (Bad Request) error.
Expand All @@ -288,8 +290,8 @@ A successful response is an HTTP 200 (OK) status containing the resource's metad

## Deleting a Resource

Knora does not normally delete resources; instead, it marks them as deleted, which means
that they do not appear in normal query results.
Knora does not normally delete resources; instead, it marks them as deleted, which means that they do not appear in
normal query results.

To mark a resource as deleted, use this route:

Expand All @@ -301,9 +303,11 @@ The request body is a JSON-LD object containing the following information about

- `@id`: the resource's IRI
- `@type`: the resource's class IRI
- `knora-api:lastModificationDate`: an `xsd:dateTimeStamp` representing the last modification date that is currently attached to the resource, if any. This is used to make sure that the resource has not been modified by someone else since you last read it.
- `knora-api:lastModificationDate`: an `xsd:dateTimeStamp` representing the last modification date that is currently
attached to the resource, if any. This is used to make sure that the resource has not been modified by someone else
since you last read it.

```jsonld
```json
{
"@id" : "http://rdfh.ch/0001/a-thing",
"@type" : "anything:Thing",
Expand All @@ -322,56 +326,93 @@ The request body is a JSON-LD object containing the following information about
}
```

The optional property `knora-api:deleteComment` specifies a comment to be attached to the
resource, explaining why it has been marked as deleted.
The optional property `knora-api:deleteComment` specifies a comment to be attached to the resource, explaining why it
has been marked as deleted.

The optional property `knora-api:deleteDate`
(an [xsd:dateTimeStamp](https://www.w3.org/TR/xmlschema11-2/#dateTimeStamp))
indicates when the resource was marked as deleted; if not given, the current
time is used.
indicates when the resource was marked as deleted; if not given, the current time is used.

The response is a JSON-LD document containing the predicate `knora-api:result` with a confirmation message.

### Requesting Deleted Resources

Resources marked as deleted are not found in search queries. It is however possible to request them directly or from an
ARK URL. In these instances, the API will not return the deleted resource, but instead a generic resource of type
`knora-base:DeletedResource`. This resource will be similar to the requested resource, having e.g. the same IRI.
The resource will contain the deletion date and optionally the deletion comment.

The response is a JSON-LD document containing the predicate `knora-api:result`
with a confirmation message.
The response to requesting a deleted resource will look as the following example:

```json
{
"rdfs:label": "Deleted Resource",
"knora-api:versionArkUrl": {
"@value": "http://0.0.0.0:3336/ark:/72163/1/0001/a=thingO.20211214T084407677335Z",
"@type": "xsd:anyURI"
},
"knora-api:attachedToProject": {
"@id": "http://rdfh.ch/projects/0001"
},
"knora-api:userHasPermission": "CR",
"knora-api:attachedToUser": {
"@id": "http://rdfh.ch/users/9XBCrDV3SRa7kS1WwynB4Q"
},
"knora-api:hasPermissions": "CR knora-admin:ProjectMember|V knora-admin:ProjectMember",
"knora-api:isDeleted": true,
"@type": "knora-api:DeletedResource",
"@id": "http://rdfh.ch/0001/a-thing",
"knora-api:deleteComment": "This resource is too boring.",
"knora-api:arkUrl": {
"@value": "http://0.0.0.0:3336/ark:/72163/1/0001/a=thingO",
"@type": "xsd:anyURI"
},
"knora-api:creationDate": {
"@value": "2021-12-14T08:44:07.677335Z",
"@type": "xsd:dateTimeStamp"
},
"knora-api:deleteDate": {
"@type": "xsd:dateTimeStamp",
"@value": "2021-12-14T08:44:07.372543Z"
},
"@context": {
"rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
"rdfs": "http://www.w3.org/2000/01/rdf-schema#",
"xsd": "http://www.w3.org/2001/XMLSchema#",
"knora-api": "http://api.knora.org/ontology/knora-api/v2#"
}
}
```

### Links to Deleted Resources

If resource `A` has a link to resource `B`, and resource
`B` is later marked as deleted, `A`'s link will still exist. DSP-API
v2 will still return the link when `A` is queried, but without any information
about `B` (except for `B`'s IRI). If `A`'s link is necessary to
meet the requirements of a cardinality, marking `B` as deleted will
not violate the cardinality.

The reason for this design is that `A` and `B` might be in
different projects, and each project must retain control of its resources
and be able to mark them as deleted, even if they are used by another
project. In future, Knora may be able to notify the owner of `A` in this
case.
`B` is later marked as deleted, `A`'s link will still exist. DSP-API v2 will still return the link when `A` is queried,
but without any information about `B` (except for `B`'s IRI). If `A`'s link is necessary to meet the requirements of a
cardinality, marking `B` as deleted will not violate the cardinality.

The reason for this design is that `A` and `B` might be in different projects, and each project must retain control of
its resources and be able to mark them as deleted, even if they are used by another project.

## Erasing a Resource from the Triplestore

Normally, resources are not actually removed from the triplestore; they are
only marked as deleted (see [Deleting a Resource](#deleting-a-resource)).
However, sometimes it is necessary to erase a resource from the triplestore.
To do so, use this route:
Normally, resources are not actually removed from the triplestore; they are only marked as deleted (see
[Deleting a Resource](#deleting-a-resource)). However, sometimes it is necessary to erase a resource from the
triplestore. To do so, use this route:

```
HTTP POST to http://host/v2/resources/erase
```

The request body is the same as for [Deleting a Resource](#deleting-a-resource),
except that `knora-api:deleteComment` is not relevant and will be ignored.
The request body is the same as for [Deleting a Resource](#deleting-a-resource), except that `knora-api:deleteComment`
is not relevant and will be ignored.

To do this, a user must be a system administrator or an administrator of the
project containing the resource. The user's permissions on the resource are
not otherwise checked.
To do this, a user must be a system administrator or an administrator of the project containing the resource. The user's
permissions on the resource are not otherwise checked.

A resource cannot be erased if any other resource has a link to it. Any such
links must first be changed or marked as deleted
(see [Updating a Value](editing-values.md#updating-a-value) and
[Deleting a Value](editing-values.md#deleting-a-value)). Then,
when the resource is erased, the deleted link values that referred to
it will also be erased.
A resource cannot be erased if any other resource has a link to it. Any such links must first be changed or marked as
deleted (see [Updating a Value](editing-values.md#updating-a-value) and
[Deleting a Value](editing-values.md#deleting-a-value)). Then, when the resource is erased, the deleted link values that
referred to it will also be erased.

This operation cannot be undone (except by restoring the repository from a
backup), so use it with care.
This operation cannot be undone (except by restoring the repository from a backup), so use it with care.