summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVivien Kraus <vivien@planete-kraus.eu>2021-06-03 18:16:10 +0200
committerVivien Kraus <vivien@planete-kraus.eu>2021-06-05 16:59:44 +0200
commit4597ca12db7ced1217f459e68a20bd6766e4a902 (patch)
tree3d63c192c8a4b1d5b5e45deca1b6ddc3c22e79ad
parent2f6dc8ba8141c52c824fedf4b56e20b4a9519c71 (diff)
Add an API to update server resource paths0.4.10
-rw-r--r--doc/webid-oidc.texi98
-rw-r--r--po/fr.po284
-rw-r--r--po/webid-oidc.pot265
-rw-r--r--src/scm/webid-oidc/errors.scm105
-rw-r--r--src/scm/webid-oidc/server/resource/Makefile.am6
-rw-r--r--src/scm/webid-oidc/server/resource/path.scm185
-rw-r--r--tests/Makefile.am3
-rw-r--r--tests/server-path.scm151
8 files changed, 809 insertions, 288 deletions
diff --git a/doc/webid-oidc.texi b/doc/webid-oidc.texi
index 66b9c6d..60ec866 100644
--- a/doc/webid-oidc.texi
+++ b/doc/webid-oidc.texi
@@ -566,6 +566,71 @@ By default, the contents are stored within @var{XDG_DATA_HOME}, but it
can be overriden by @var{#:dir}.
@end deffn
+The @emph{path} API is defined in
+@code{(webid-oidc server resource path)}.
+
+@deffn function read-path @var{path}
+Read the resource at @var{path}, and return 2 values:
+@enumerate
+@item
+the ETag of the main resource;
+@item
+an alist where keys are auxiliary resource type URIs (the type is from
+@code{(web uri)}), and the values are ETags of the corresponding
+resource.
+@end enumerate
+
+If the resource is not found, raise an exception with type
+@code{&path-not-found}, and maybe @code{&uri-slash-semantics-error} if
+a resource with a different ending-in-slash exists.
+
+This function is safe to call when the path is being modified, either
+by another thread, process or else, as the returned values will always
+be consistent. However, once the function returns, an updating process
+may have deleted the returned ETags. If this is the case, then you
+must call this function again to read the updated path.
+@end deffn
+
+@deffn function update-path @var{path} @var{f} @var{content-type} @var{contained} @var{static-content} @var{create} @var{delete} [@var{#:create-intermediate-containers?}=@code{#f}]
+Read @var{path}, call @var{f} with two values: the ETag and the
+auxiliary ETags (as returned by @var{read-path}), and update the path
+accordingly. If @var{path} does not exist, then the first argument is
+@code{#f} and the second one is the empty list.
+
+If @var{f} returns @code{#f}, then the resource is deleted.
+
+If @var{f} returns an ETag as the first returned value and an alist of
+auxiliary resource ETags as the second value, then the resource is
+updated.
+
+The last functions are from the content API. Since creating or
+deleting children requires updating the parent, we need them.
+
+Some operations should create the intermediate containers for a given
+path, this is the case for the @code{PUT} HTTP verb. For @code{POST},
+the parent should exist. The @var{#:create-intermediate-containers?}
+switch lets you change the behavior. In any case, it is an error to
+delete a non-empty container.
+
+The update is atomic, meaning that at any point in time the file is
+fully written out. Concurrent access to the same resource is performed
+by locking the lock file named @var{X}/@var{Y}.lock, where @var{X} is
+the first character of the base64-url sha-256 hash of the path, and
+@var{Y} is the other characters. @strong{The lock file is not meant to
+be removed} when the resource is unlocked. It should be locked with
+@code{flock} instead.
+
+Also, the API uses a global mutex to prevent concurrent updates. So,
+if @var{f} tries to update some other paths, then a deadlock will
+ensue.
+
+If the resource is created or deleted, then the parent resource is
+updated as well. To avoid deadlocks with other processes, please
+follow the following rules: lock the path, then lock the parent path,
+then update the parent, then unlock the parent, and finally unlock the
+child path.
+@end deffn
+
@node Running a client
@chapter Running a client
@@ -731,6 +796,7 @@ Return a string explaining the @var{error}. You can limit the
* Invalid JWT::
* Cannot fetch data on the web::
* Other errors in the protocol or from a reasonable implementation::
+* Server-side errors::
@end menu
@node Invalid data format
@@ -1131,6 +1197,38 @@ The @var{webid}, as certified by @var{iss}, cannot be refreshed
because we don’t have a refresh token stored in @var{dir}.
@end deftp
+@node Server-side errors
+@section Server-side errors
+The resource server implementation may encounter some more exceptional
+conditions.
+
+@deftp {exception type} &path-not-found @var{path}
+There is no registered resource at @var{path}.
+@end deftp
+
+@deftp {exception type} &uri-slash-semantics-error @var{path} @var{expected-path}
+While the resource at @var{path} does not exist, the resource at
+@var{expected-path} does, and @var{path} and @var{expected-path}
+differ only by a trailing slash. This exception may be raised along
+with @code{&path-not-found}.
+
+Beware that even if it is true at the time when the exception is
+created, maybe the resource has been created by the time it is
+handled.
+@end deftp
+
+@deftp {exception type} &cannot-delete-root
+There was a request to delete the root storage, which is an error.
+@end deftp
+
+@deftp {exception type} &container-not-empty @var{path}
+There was a request to delete a non-empty container.
+@end deftp
+
+@deftp {exception type} &not-a-container @var{path} @var{content-type}
+There was a request to create a resource in something that is not a
+container.
+@end deftp
@node GNU Free Documentation License
@appendix GNU Free Documentation License
diff --git a/po/fr.po b/po/fr.po
index 3af1d8e..2c499ab 100644
--- a/po/fr.po
+++ b/po/fr.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: webid-oidc 0.0.0\n"
"Report-Msgid-Bugs-To: vivien@planete-kraus.eu\n"
-"POT-Creation-Date: 2021-06-05 16:22+0200\n"
+"POT-Creation-Date: 2021-06-05 16:23+0200\n"
"PO-Revision-Date: 2021-06-05 11:07+0200\n"
"Last-Translator: Vivien Kraus <vivien@planete-kraus.eu>\n"
"Language-Team: French <vivien@planete-kraus.eu>\n"
@@ -126,101 +126,101 @@ msgstr "Utilisation : generate-random [NOMBRE D'OCTETS]\n"
msgid "Usage: generate-key [NUMBER OF BITS | CURVE]\n"
msgstr "Utilisation : generate-key [NOMBRE DE BITS | COURBE]\n"
-#: src/scm/webid-oidc/errors.scm:881
+#: src/scm/webid-oidc/errors.scm:931
msgid "that’s how it is"
msgstr "c’est comme ça"
-#: src/scm/webid-oidc/errors.scm:886
+#: src/scm/webid-oidc/errors.scm:936
#, scheme-format
msgid "the value ~s is not a base64 string (because ~a)"
msgstr "la valeur ~s n’est pas une chaîne base64 (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:889
+#: src/scm/webid-oidc/errors.scm:939
#, scheme-format
msgid "the value ~s is not JSON (because ~a)"
msgstr "la valeur ~s n’est pas du JSON (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:892
+#: src/scm/webid-oidc/errors.scm:942
#, scheme-format
msgid "the value ~s is not Turtle (because ~a)"
msgstr "la valeur ~s n’est pas du Turtle (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:895
+#: src/scm/webid-oidc/errors.scm:945
#, scheme-format
msgid "the value ~s does not identify an elleptic curve"
msgstr "la valeur ~s n’identifie pas une courbe elliptique"
-#: src/scm/webid-oidc/errors.scm:900
+#: src/scm/webid-oidc/errors.scm:950
#, scheme-format
msgid "the value ~s does not identify a JWK (because ~a)"
msgstr "la valeur ~s n’identifie pas une JWK (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:902
+#: src/scm/webid-oidc/errors.scm:952
#, scheme-format
msgid "the value ~s does not identify a JWK"
msgstr "la valeur ~s n’identifie pas une JWK"
-#: src/scm/webid-oidc/errors.scm:907
+#: src/scm/webid-oidc/errors.scm:957
#, scheme-format
msgid "the value ~s does not identify a public JWK (because ~a)"
msgstr "la valeur ~s n’identifie pas une JWK publique (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:909
+#: src/scm/webid-oidc/errors.scm:959
#, scheme-format
msgid "the value ~s does not identify a public JWK"
msgstr "la valeur ~s n’identifie pas une JWK publique"
-#: src/scm/webid-oidc/errors.scm:914
+#: src/scm/webid-oidc/errors.scm:964
#, scheme-format
msgid "the value ~s does not identify a private JWK (because ~a)"
msgstr "la valeur ~s n’identifie pas une JWK privée (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:916
+#: src/scm/webid-oidc/errors.scm:966
#, scheme-format
msgid "the value ~s does not identify a private JWK"
msgstr "la valeur ~s n’identifie pas une JWK privée"
-#: src/scm/webid-oidc/errors.scm:921
+#: src/scm/webid-oidc/errors.scm:971
#, scheme-format
msgid "the value ~s does not identify a JWKS (because ~a)"
msgstr "la valeur ~s n’identifie pas un JWKS (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:923
+#: src/scm/webid-oidc/errors.scm:973
#, scheme-format
msgid "the value ~s does not identify a JWKS"
msgstr "la valeur ~s n’identifie pas un JWKS"
-#: src/scm/webid-oidc/errors.scm:926
+#: src/scm/webid-oidc/errors.scm:976
#, scheme-format
msgid "the value ~s does not identify a hash algorithm"
msgstr "la valeur ~s n’identifie pas un algorithme de hachage"
-#: src/scm/webid-oidc/errors.scm:929
+#: src/scm/webid-oidc/errors.scm:979
#, scheme-format
msgid "the value ~s is not an alist or misses key ~s"
msgstr "la valeur ~s n’est pas une alist ou il manque la clé ~s"
-#: src/scm/webid-oidc/errors.scm:932
+#: src/scm/webid-oidc/errors.scm:982
#, scheme-format
msgid "the value ~s is not a JWS header (because ~a)"
msgstr "la valeur ~s n’est pas un header JWS (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:935
+#: src/scm/webid-oidc/errors.scm:985
#, scheme-format
msgid "the value ~s is not a JWS payload (because ~a)"
msgstr "la valeur ~s n’est pas un contenu JWS (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:938
+#: src/scm/webid-oidc/errors.scm:988
#, scheme-format
msgid "the value ~s is not a JWS (because ~a)"
msgstr "la valeur ~s n’est pas un JWS (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:941
+#: src/scm/webid-oidc/errors.scm:991
#, scheme-format
msgid "the string ~s cannot be split in 3 parts with ~s"
msgstr "la chaîne ~s ne peut pas être découpée en 3 parties avec ~s"
-#: src/scm/webid-oidc/errors.scm:944
+#: src/scm/webid-oidc/errors.scm:994
#, scheme-format
msgid ""
"all key candidates failed to verify signature ~s with algorithm ~s and "
@@ -229,17 +229,17 @@ msgstr ""
"aucune clé candidate n’a pu vérifier la signature ~s avec l’algorithme ~s et "
"le contenu ~a (il y en avait ~a : ~s)"
-#: src/scm/webid-oidc/errors.scm:947
+#: src/scm/webid-oidc/errors.scm:997
#, scheme-format
msgid "I cannot decode JWS ~a (because ~a)"
msgstr "je n’ai pas pu décoder le JWS encodé par ~a (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:950
+#: src/scm/webid-oidc/errors.scm:1000
#, scheme-format
msgid "I cannot encode JWS ~a (because ~a)"
msgstr "je n’ai pas pu encoder le JWS ~a (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:953
+#: src/scm/webid-oidc/errors.scm:1003
#, scheme-format
msgid ""
"the server request unexpectedly failed with code ~a and reason phrase ~s"
@@ -247,338 +247,338 @@ msgstr ""
"la requête au serveur a échoué de façon inattendue avec un code ~a et une "
"raison ~s"
-#: src/scm/webid-oidc/errors.scm:958
+#: src/scm/webid-oidc/errors.scm:1008
#, scheme-format
msgid "the header ~a should not have the value ~s"
msgstr "l’en-tête ~a ne devrait pas avoir la valeur ~s"
-#: src/scm/webid-oidc/errors.scm:960
+#: src/scm/webid-oidc/errors.scm:1010
#, scheme-format
msgid "the header ~a should be present"
msgstr "l’en-tête ~a devrait être présent"
-#: src/scm/webid-oidc/errors.scm:963
+#: src/scm/webid-oidc/errors.scm:1013
#, scheme-format
msgid "the server response wasn't expected: ~s (because ~a)"
msgstr "la réponse du serveur est inattendue : ~s (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:969
+#: src/scm/webid-oidc/errors.scm:1019
#, scheme-format
msgid "the value ~s is not an OIDC configuration (because ~a)"
msgstr "la valeur ~s n’est pas une configuration OIDC (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:974
+#: src/scm/webid-oidc/errors.scm:1024
#, scheme-format
msgid "the webid field is incorrect: ~s"
msgstr "le champ webid est incorrect : ~s"
-#: src/scm/webid-oidc/errors.scm:975
+#: src/scm/webid-oidc/errors.scm:1025
msgid "the webid field is missing"
msgstr "le champ webid est manquant"
-#: src/scm/webid-oidc/errors.scm:979
+#: src/scm/webid-oidc/errors.scm:1029
#, scheme-format
msgid "the sub field is incorrect: ~s"
msgstr "le champ sub est incorrect : ~s"
-#: src/scm/webid-oidc/errors.scm:980
+#: src/scm/webid-oidc/errors.scm:1030
msgid "the sub field is missing"
msgstr "le champ sub est manquant"
-#: src/scm/webid-oidc/errors.scm:984
+#: src/scm/webid-oidc/errors.scm:1034
#, scheme-format
msgid "the iss field is incorrect: ~s"
msgstr "le champ iss est incorrect : ~s"
-#: src/scm/webid-oidc/errors.scm:985
+#: src/scm/webid-oidc/errors.scm:1035
msgid "the iss field is missing"
msgstr "le champ iss est manquant"
-#: src/scm/webid-oidc/errors.scm:989
+#: src/scm/webid-oidc/errors.scm:1039
#, scheme-format
msgid "the aud field is incorrect: ~s"
msgstr "le champ aud est incorrect : ~s"
-#: src/scm/webid-oidc/errors.scm:990
+#: src/scm/webid-oidc/errors.scm:1040
msgid "the aud field is missing"
msgstr "le champ aud est manquant"
-#: src/scm/webid-oidc/errors.scm:994
+#: src/scm/webid-oidc/errors.scm:1044
#, scheme-format
msgid "the iat field is incorrect: ~s"
msgstr "le champ iat est incorrect : ~s"
-#: src/scm/webid-oidc/errors.scm:995
+#: src/scm/webid-oidc/errors.scm:1045
msgid "the iat field is missing"
msgstr "le champ iat est manquant"
-#: src/scm/webid-oidc/errors.scm:999
+#: src/scm/webid-oidc/errors.scm:1049
#, scheme-format
msgid "the exp field is incorrect: ~s"
msgstr "le champ exp est incorrect : ~s"
-#: src/scm/webid-oidc/errors.scm:1000
+#: src/scm/webid-oidc/errors.scm:1050
msgid "the exp field is missing"
msgstr "le champ exp est manquant"
-#: src/scm/webid-oidc/errors.scm:1004
+#: src/scm/webid-oidc/errors.scm:1054
#, scheme-format
msgid "the cnf/jkt field is incorrect: ~s"
msgstr "le champ cnf/jkt est incorrect : ~s"
-#: src/scm/webid-oidc/errors.scm:1005
+#: src/scm/webid-oidc/errors.scm:1055
msgid "the cnf/jkt field is missing"
msgstr "le champ cnf/jkt est manquant"
-#: src/scm/webid-oidc/errors.scm:1009
+#: src/scm/webid-oidc/errors.scm:1059
#, scheme-format
msgid "the client-id field is incorrect: ~s"
msgstr "le champ client-id est incorrect : ~s"
-#: src/scm/webid-oidc/errors.scm:1010
+#: src/scm/webid-oidc/errors.scm:1060
msgid "the client-id field is missing"
msgstr "le champ client-id est manquant"
-#: src/scm/webid-oidc/errors.scm:1014
+#: src/scm/webid-oidc/errors.scm:1064
#: src/scm/webid-oidc/authorization-page-unsafe.scm:133
#, scheme-format
msgid "the redirect_uris field is incorrect: ~s"
msgstr "le champ redirect_uris est incorrect : ~s"
-#: src/scm/webid-oidc/errors.scm:1015
+#: src/scm/webid-oidc/errors.scm:1065
#: src/scm/webid-oidc/authorization-page-unsafe.scm:134
msgid "the redirect_uris field is missing"
msgstr "le champ redirect_uris est manquant"
-#: src/scm/webid-oidc/errors.scm:1019
+#: src/scm/webid-oidc/errors.scm:1069
#, scheme-format
msgid "the typ field is incorrect: ~s"
msgstr "le champ typ est incorrect : ~s"
-#: src/scm/webid-oidc/errors.scm:1020
+#: src/scm/webid-oidc/errors.scm:1070
msgid "the typ field is missing"
msgstr "le champ typ est manquant"
-#: src/scm/webid-oidc/errors.scm:1024
+#: src/scm/webid-oidc/errors.scm:1074
#, scheme-format
msgid "the jwk field is incorrect: ~s (because ~a)"
msgstr "le champ jwk est incorrect : ~s (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:1026
+#: src/scm/webid-oidc/errors.scm:1076
msgid "the jwk field is missing"
msgstr "le champ jwk est manquant"
-#: src/scm/webid-oidc/errors.scm:1030
+#: src/scm/webid-oidc/errors.scm:1080
#, scheme-format
msgid "the jti field is incorrect: ~s"
msgstr "le champ jti est incorrect : ~s"
-#: src/scm/webid-oidc/errors.scm:1031
+#: src/scm/webid-oidc/errors.scm:1081
msgid "the jti field is missing"
msgstr "le champ jti est manquant"
-#: src/scm/webid-oidc/errors.scm:1035
+#: src/scm/webid-oidc/errors.scm:1085
#, scheme-format
msgid "the nonce field is incorrect: ~s"
msgstr "le champ nonce est incorrect : ~s"
-#: src/scm/webid-oidc/errors.scm:1036
+#: src/scm/webid-oidc/errors.scm:1086
msgid "the nonce field is missing"
msgstr "le champ nonce est manquant"
-#: src/scm/webid-oidc/errors.scm:1040
+#: src/scm/webid-oidc/errors.scm:1090
#, scheme-format
msgid "the htm field is incorrect: ~s"
msgstr "le champ htm est incorrect : ~s"
-#: src/scm/webid-oidc/errors.scm:1041
+#: src/scm/webid-oidc/errors.scm:1091
msgid "the htm field is missing"
msgstr "le champ htm est manquant"
-#: src/scm/webid-oidc/errors.scm:1045
+#: src/scm/webid-oidc/errors.scm:1095
#, scheme-format
msgid "the htu field is incorrect: ~s"
msgstr "le champ htu est incorrect : ~s"
-#: src/scm/webid-oidc/errors.scm:1046
+#: src/scm/webid-oidc/errors.scm:1096
msgid "the htu field is missing"
msgstr "le champ htu est manquant"
-#: src/scm/webid-oidc/errors.scm:1048
+#: src/scm/webid-oidc/errors.scm:1098
#, scheme-format
msgid "~s is not an access token (because ~a)"
msgstr "~s n’est pas un jeton d’accès (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:1051
+#: src/scm/webid-oidc/errors.scm:1101
#, scheme-format
msgid "~s is not an access token header (because ~a)"
msgstr "~s n’est pas un en-tête de jeton d’accès (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:1054
+#: src/scm/webid-oidc/errors.scm:1104
#, scheme-format
msgid "~s is not an access token payload (because ~a)"
msgstr "~s n’est pas un contenu de jeton d’accès (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:1057
+#: src/scm/webid-oidc/errors.scm:1107
#, scheme-format
msgid "~s is not a DPoP proof (because ~a)"
msgstr "~s n’est pas une preuve DPoP (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:1060
+#: src/scm/webid-oidc/errors.scm:1110
#, scheme-format
msgid "~s is not a DPoP proof header (because ~a)"
msgstr "~s n’est pas un en-tête de preuve DPoP (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:1063
+#: src/scm/webid-oidc/errors.scm:1113
#, scheme-format
msgid "~s is not a DPoP proof payload (because ~a)"
msgstr "~s n’est pas un contenu de preuve DPoP (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:1066
+#: src/scm/webid-oidc/errors.scm:1116
#, scheme-format
msgid "I cannot fetch the issuer configuration of ~a (because ~a)"
msgstr ""
"je n’ai pas pu récupérer la configuration de l’émetteur ~a (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:1073
+#: src/scm/webid-oidc/errors.scm:1123
#, scheme-format
msgid "I cannot fetch the JWKS of ~a at ~a (because ~a)"
msgstr "je n’ai pas pu récupérer le JWKS de ~a à ~a (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:1084
+#: src/scm/webid-oidc/errors.scm:1134
#, scheme-format
msgid "the HTTP method is signed for ~s, but ~s was requested"
msgstr "la méthode HTTP a été signée pour ~s, mais ~s a été demandé"
-#: src/scm/webid-oidc/errors.scm:1087
+#: src/scm/webid-oidc/errors.scm:1137
#, scheme-format
msgid "the HTTP uri is signed for ~a, but ~a was requested"
msgstr "l’uri HTTP a été signé pour ~a, mais ~a a été demandé"
-#: src/scm/webid-oidc/errors.scm:1090
+#: src/scm/webid-oidc/errors.scm:1140
#, scheme-format
msgid "the date is ~a, but the DPoP proof is signed in the future at ~a"
msgstr "la date est ~a, mais la preuve DPoP a été signée dans le futur à ~a"
-#: src/scm/webid-oidc/errors.scm:1094
+#: src/scm/webid-oidc/errors.scm:1144
#, scheme-format
msgid "the date is ~a, but the DPoP proof was signed too long ago at ~a"
msgstr ""
"la date est ~a, mais la preuve DPoP a été signée il y a trop longtemps à ~a"
-#: src/scm/webid-oidc/errors.scm:1103
+#: src/scm/webid-oidc/errors.scm:1153
#, scheme-format
msgid "the key ~s does not hash to ~a"
msgstr "la clé ~s ne donne pas un hash de ~a"
-#: src/scm/webid-oidc/errors.scm:1105
+#: src/scm/webid-oidc/errors.scm:1155
#, scheme-format
msgid "the key confirmation of ~s failed (because ~a)"
msgstr "la confirmation de clé de ~s a échoué (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:1107
+#: src/scm/webid-oidc/errors.scm:1157
#, scheme-format
msgid "the key confirmation of ~s failed"
msgstr "la confirmation de la clé ~s a échoué"
-#: src/scm/webid-oidc/errors.scm:1109
+#: src/scm/webid-oidc/errors.scm:1159
#, scheme-format
msgid "the jti ~s has already been found (because ~a)"
msgstr "le jti ~s a déjà été trouvé (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:1112
+#: src/scm/webid-oidc/errors.scm:1162
#, scheme-format
msgid "I cannot decode ~s as an access token (because ~a)"
msgstr "je n’ai pas pu décoder ~s comme jeton d’accès (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:1115
+#: src/scm/webid-oidc/errors.scm:1165
#, scheme-format
msgid "I cannot encode ~s as an access token with key ~s (because ~a)"
msgstr ""
"je n’ai pas pu encoder ~s comme un jeton d’accès avec la clé ~s (parce que "
"~a)"
-#: src/scm/webid-oidc/errors.scm:1118
+#: src/scm/webid-oidc/errors.scm:1168
#, scheme-format
msgid "I cannot decode ~s as a DPoP proof (because ~a)"
msgstr "je n’ai pas pu décoder ~s comme preuve DPoP (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:1121
+#: src/scm/webid-oidc/errors.scm:1171
#, scheme-format
msgid "I cannot encode ~s as a DPoP proof (because ~a)"
msgstr "je n’ai pas pu encoder ~s comme une preuve DPoP (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:1124
+#: src/scm/webid-oidc/errors.scm:1174
#, scheme-format
msgid "I could not fetch a RDF graph at ~a (because ~a)"
msgstr "je n’ai pas pu récupérer de graphe RDF à ~a (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:1127
+#: src/scm/webid-oidc/errors.scm:1177
#, scheme-format
msgid "~s is not a client manifest (because ~a)"
msgstr "~s n’est pas un manifeste client (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:1130
+#: src/scm/webid-oidc/errors.scm:1180
#, scheme-format
msgid "~s does not authorize redirection URI ~a"
msgstr "~s n’autorise pas l’URI de redirection ~a"
-#: src/scm/webid-oidc/errors.scm:1133
+#: src/scm/webid-oidc/errors.scm:1183
msgid "I cannot serve a public manifest"
msgstr "je ne peux pas servir un manifeste public"
-#: src/scm/webid-oidc/errors.scm:1135
+#: src/scm/webid-oidc/errors.scm:1185
#, scheme-format
msgid "~a does not have a client manifest registration triple"
msgstr "~a n’a pas de triplet d’enregistrement de manifeste client"
-#: src/scm/webid-oidc/errors.scm:1138
+#: src/scm/webid-oidc/errors.scm:1188
#, scheme-format
msgid "the client manifest at ~a is advertised for ~a"
msgstr "le manifeste client ~a est publié pour ~a"
-#: src/scm/webid-oidc/errors.scm:1141
+#: src/scm/webid-oidc/errors.scm:1191
#, scheme-format
msgid "I could not fetch the client manifest of ~a (because ~a)"
msgstr "je n’ai pas pu récupérer le manifeste client de ~a (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:1144
+#: src/scm/webid-oidc/errors.scm:1194
#, scheme-format
msgid "~s is not an authorization code (because ~a)"
msgstr "~s n’est pas un code d’autorisation (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:1147
+#: src/scm/webid-oidc/errors.scm:1197
#, scheme-format
msgid "~s is not an authorization code header (because ~a)"
msgstr "~s n’est pas un en-tête de code d’autorisation (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:1150
+#: src/scm/webid-oidc/errors.scm:1200
#, scheme-format
msgid "~s is not an authorization code payload (because ~a)"
msgstr "~s n’est pas un contenu de code d’autorisation (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:1153
+#: src/scm/webid-oidc/errors.scm:1203
#, scheme-format
msgid "the current time is ~a, and the authorization code expired at ~a"
msgstr ""
"la date est actuellement ~a, et le code d’autorisation a expiré à la date ~a"
-#: src/scm/webid-oidc/errors.scm:1157
+#: src/scm/webid-oidc/errors.scm:1207
#, scheme-format
msgid "I cannot decode ~s as an authorization code (because ~a)"
msgstr "je n’ai pas pu décoder ~s comme un code d’autorisation (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:1160
+#: src/scm/webid-oidc/errors.scm:1210
#, scheme-format
msgid "I cannot encode ~s as an authorization code (because ~a)"
msgstr "je n’ai pas pu encoder ~s comme un code d’autorisation (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:1163
+#: src/scm/webid-oidc/errors.scm:1213
#, scheme-format
msgid "there is no such refresh token as ~s"
msgstr "il n’y a pas de jeton de rafraîchissement ~s"
-#: src/scm/webid-oidc/errors.scm:1166
+#: src/scm/webid-oidc/errors.scm:1216
#, scheme-format
msgid ""
"the refresh token is bound to a key confirmed as ~s, but it is used with key "
@@ -587,45 +587,45 @@ msgstr ""
"Le jeton de rafraîchissement est lié à une clé confirmée par ~s, mais il est "
"utilisé avec la clé ~s"
-#: src/scm/webid-oidc/errors.scm:1169
+#: src/scm/webid-oidc/errors.scm:1219
#, scheme-format
msgid "I cannot decode ~s as an ID token (because ~a)"
msgstr "je n’ai pas pu décoder ~s comme jeton d’identité (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:1172
+#: src/scm/webid-oidc/errors.scm:1222
#, scheme-format
msgid "I cannot encode ~s as an ID token (because ~a)"
msgstr "je n’ai pas pu encoder ~s comme un jeton d’identité (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:1175
+#: src/scm/webid-oidc/errors.scm:1225
#, scheme-format
msgid "the grant type ~s is not supported"
msgstr "le type d’octroi ~s n’est pas supporté "
-#: src/scm/webid-oidc/errors.scm:1178
+#: src/scm/webid-oidc/errors.scm:1228
msgid "there is no authorization code in the request"
msgstr "il n’y a pas de code d’autorisation dans la requête"
-#: src/scm/webid-oidc/errors.scm:1180
+#: src/scm/webid-oidc/errors.scm:1230
msgid "there is no refresh token in the request"
msgstr "il n’y a pas de jeton de rafraîchissement dans la requête"
-#: src/scm/webid-oidc/errors.scm:1182
+#: src/scm/webid-oidc/errors.scm:1232
#, scheme-format
msgid "~s is not an ID token (because ~a)"
msgstr "~s n’est pas un jeton d’identité (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:1185
+#: src/scm/webid-oidc/errors.scm:1235
#, scheme-format
msgid "~s is not an ID token header (because ~a)"
msgstr "~s n’est pas un en-tête de jeton d’identité (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:1188
+#: src/scm/webid-oidc/errors.scm:1238
#, scheme-format
msgid "~s is not an ID token payload (because ~a)"
msgstr "~s n’est pas un contenu de jeton d’identité (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:1191
+#: src/scm/webid-oidc/errors.scm:1241
#, scheme-format
msgid ""
"I couldn’t set the locale to ~s as an approximation of the client locale ~s"
@@ -633,12 +633,12 @@ msgstr ""
"je n’ai pas pu définir la locale à ~s comme approximation de la locale du "
"client ~s"
-#: src/scm/webid-oidc/errors.scm:1194
+#: src/scm/webid-oidc/errors.scm:1244
#, scheme-format
msgid "~s does not admit ~s as an identity provider"
msgstr "~s n’admet pas ~s comme fournisseur d’identité"
-#: src/scm/webid-oidc/errors.scm:1197
+#: src/scm/webid-oidc/errors.scm:1247
#, scheme-format
msgid ""
"~a is neither an identity provider (because ~a) nor a webid (because ~a)"
@@ -646,92 +646,113 @@ msgstr ""
"~a n’est ni un fournisseur d’identité (parce que ~a) ni un webid (parce que "
"~a)"
-#: src/scm/webid-oidc/errors.scm:1202
+#: src/scm/webid-oidc/errors.scm:1252
#, scheme-format
msgid "the token request failed (because ~a)"
msgstr "la requête de jeton a échoué (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:1205
+#: src/scm/webid-oidc/errors.scm:1255
#, scheme-format
msgid "you don’t have a refresh token for identity ~a certified by ~a in ~s"
msgstr ""
"vous n’avez pas de jeton de rafraîchissement pour l’identité ~a certifié par "
"~a dans ~s"
-#: src/scm/webid-oidc/errors.scm:1210
+#: src/scm/webid-oidc/errors.scm:1260
#, scheme-format
msgid "all identity provider candidates for ~a failed: ~a"
msgstr "tous les candidats de fournisseurs d’identité pour ~a ont échoué : ~a"
-#: src/scm/webid-oidc/errors.scm:1214
+#: src/scm/webid-oidc/errors.scm:1264
#, scheme-format
msgid "~s failed (because ~a)"
msgstr "~s a échoué (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:1217
+#: src/scm/webid-oidc/errors.scm:1267
msgid ", "
msgstr ", "
-#: src/scm/webid-oidc/errors.scm:1221
+#: src/scm/webid-oidc/errors.scm:1269
+#, scheme-format
+msgid "no resource has been found to serve URI path ~s"
+msgstr "aucune ressource n’a été trouvée pour servir le chemin d’URI ~s"
+
+#: src/scm/webid-oidc/errors.scm:1272
+#, scheme-format
+msgid "no resource has been found to serve URI path ~s, but ~s exists"
+msgstr ""
+"aucune ressource n’a été trouvée pour servir le chemin d’URI ~s, mais ~s "
+"existe"
+
+#: src/scm/webid-oidc/errors.scm:1275
+msgid "the root storage cannot be deleted"
+msgstr "le stockage racine ne peut pas être détruit"
+
+#: src/scm/webid-oidc/errors.scm:1277
+#, scheme-format
+msgid "the container ~s should be emptied before being deleted"
+msgstr "le conteneur ~s doit être vidé avant d’être détruit"
+
+#: src/scm/webid-oidc/errors.scm:1282
msgid "that’s it"
msgstr "c’est tout"
-#: src/scm/webid-oidc/errors.scm:1225
+#: src/scm/webid-oidc/errors.scm:1286
#, scheme-format
msgid "~a and ~a"
msgstr "~a et ~a"
-#: src/scm/webid-oidc/errors.scm:1228
+#: src/scm/webid-oidc/errors.scm:1289
#, scheme-format
msgid "~a, ~a"
msgstr "~a, ~a"
-#: src/scm/webid-oidc/errors.scm:1232
+#: src/scm/webid-oidc/errors.scm:1293
#, scheme-format
msgid "the signature ~a does not match key ~s with payload ~a"
msgstr "la signature ~a ne correspond pas à la clé ~s avec le contenu ~a"
-#: src/scm/webid-oidc/errors.scm:1235
+#: src/scm/webid-oidc/errors.scm:1296
msgid "there is an undefined variable"
msgstr "il y a une variable non définie"
-#: src/scm/webid-oidc/errors.scm:1237
+#: src/scm/webid-oidc/errors.scm:1298
#, scheme-format
msgid "the origin is ~a"
msgstr "l’origine est ~a"
-#: src/scm/webid-oidc/errors.scm:1240
+#: src/scm/webid-oidc/errors.scm:1301
#, scheme-format
msgid "a message is attached: ~a"
msgstr "un message est attaché : ~a"
-#: src/scm/webid-oidc/errors.scm:1243
+#: src/scm/webid-oidc/errors.scm:1304
#, scheme-format
msgid "the values ~s are problematic"
msgstr "les valeurs ~s sont problématiques"
-#: src/scm/webid-oidc/errors.scm:1246
+#: src/scm/webid-oidc/errors.scm:1307
msgid "there is a kind and args"
msgstr "il y a un type et des arguments"
-#: src/scm/webid-oidc/errors.scm:1248
+#: src/scm/webid-oidc/errors.scm:1309
msgid "there is an assertion failure"
msgstr "il y a un échec d’assertion"
-#: src/scm/webid-oidc/errors.scm:1250
+#: src/scm/webid-oidc/errors.scm:1311
#, scheme-format
msgid "the program quits with code ~a"
msgstr "le programme quitte avec le code ~a"
-#: src/scm/webid-oidc/errors.scm:1253
+#: src/scm/webid-oidc/errors.scm:1314
msgid "the program cannot recover from this exception"
msgstr "le programme ne peut pas récupérer après cette exception"
-#: src/scm/webid-oidc/errors.scm:1255
+#: src/scm/webid-oidc/errors.scm:1316
msgid "there is an error"
msgstr "il y a une erreur"
-#: src/scm/webid-oidc/errors.scm:1257
+#: src/scm/webid-oidc/errors.scm:1318
#, scheme-format
msgid "Unhandled exception type ~a."
msgstr "Type d’exception non pris en charge ~a."
@@ -1615,23 +1636,6 @@ msgstr "Il y a eu une erreur : ~a\n"
#~ msgid "the group ~a cannot be fetched (because ~a)"
#~ msgstr "le groupe ~a n’a pas pu être récupéré (parce que ~a)"
-#, scheme-format
-#~ msgid "no resource has been found to serve URI path ~s"
-#~ msgstr "aucune ressource n’a été trouvée pour servir le chemin d’URI ~s"
-
-#, scheme-format
-#~ msgid "no resource has been found to serve URI path ~s, but ~s exists"
-#~ msgstr ""
-#~ "aucune ressource n’a été trouvée pour servir le chemin d’URI ~s, mais ~s "
-#~ "existe"
-
-#~ msgid "the root storage cannot be deleted"
-#~ msgstr "le stockage racine ne peut pas être détruit"
-
-#, scheme-format
-#~ msgid "the container ~s should be emptied before being deleted"
-#~ msgstr "le conteneur ~s doit être vidé avant d’être détruit"
-
#~ msgid "there is an external error"
#~ msgstr "il y a une erreur externe"
diff --git a/po/webid-oidc.pot b/po/webid-oidc.pot
index fdfad63..7653461 100644
--- a/po/webid-oidc.pot
+++ b/po/webid-oidc.pot
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: webid-oidc SNAPSHOT\n"
"Report-Msgid-Bugs-To: vivien@planete-kraus.eu\n"
-"POT-Creation-Date: 2021-06-05 16:22+0200\n"
+"POT-Creation-Date: 2021-06-05 16:23+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -122,595 +122,614 @@ msgstr ""
msgid "Usage: generate-key [NUMBER OF BITS | CURVE]\n"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:881
+#: src/scm/webid-oidc/errors.scm:931
msgid "that’s how it is"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:886
+#: src/scm/webid-oidc/errors.scm:936
#, scheme-format
msgid "the value ~s is not a base64 string (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:889
+#: src/scm/webid-oidc/errors.scm:939
#, scheme-format
msgid "the value ~s is not JSON (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:892
+#: src/scm/webid-oidc/errors.scm:942
#, scheme-format
msgid "the value ~s is not Turtle (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:895
+#: src/scm/webid-oidc/errors.scm:945
#, scheme-format
msgid "the value ~s does not identify an elleptic curve"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:900
+#: src/scm/webid-oidc/errors.scm:950
#, scheme-format
msgid "the value ~s does not identify a JWK (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:902
+#: src/scm/webid-oidc/errors.scm:952
#, scheme-format
msgid "the value ~s does not identify a JWK"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:907
+#: src/scm/webid-oidc/errors.scm:957
#, scheme-format
msgid "the value ~s does not identify a public JWK (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:909
+#: src/scm/webid-oidc/errors.scm:959
#, scheme-format
msgid "the value ~s does not identify a public JWK"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:914
+#: src/scm/webid-oidc/errors.scm:964
#, scheme-format
msgid "the value ~s does not identify a private JWK (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:916
+#: src/scm/webid-oidc/errors.scm:966
#, scheme-format
msgid "the value ~s does not identify a private JWK"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:921
+#: src/scm/webid-oidc/errors.scm:971
#, scheme-format
msgid "the value ~s does not identify a JWKS (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:923
+#: src/scm/webid-oidc/errors.scm:973
#, scheme-format
msgid "the value ~s does not identify a JWKS"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:926
+#: src/scm/webid-oidc/errors.scm:976
#, scheme-format
msgid "the value ~s does not identify a hash algorithm"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:929
+#: src/scm/webid-oidc/errors.scm:979
#, scheme-format
msgid "the value ~s is not an alist or misses key ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:932
+#: src/scm/webid-oidc/errors.scm:982
#, scheme-format
msgid "the value ~s is not a JWS header (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:935
+#: src/scm/webid-oidc/errors.scm:985
#, scheme-format
msgid "the value ~s is not a JWS payload (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:938
+#: src/scm/webid-oidc/errors.scm:988
#, scheme-format
msgid "the value ~s is not a JWS (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:941
+#: src/scm/webid-oidc/errors.scm:991
#, scheme-format
msgid "the string ~s cannot be split in 3 parts with ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:944
+#: src/scm/webid-oidc/errors.scm:994
#, scheme-format
msgid ""
"all key candidates failed to verify signature ~s with algorithm ~s and "
"payload ~a (there were ~a: ~s)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:947
+#: src/scm/webid-oidc/errors.scm:997
#, scheme-format
msgid "I cannot decode JWS ~a (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:950
+#: src/scm/webid-oidc/errors.scm:1000
#, scheme-format
msgid "I cannot encode JWS ~a (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:953
+#: src/scm/webid-oidc/errors.scm:1003
#, scheme-format
msgid ""
"the server request unexpectedly failed with code ~a and reason phrase ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:958
+#: src/scm/webid-oidc/errors.scm:1008
#, scheme-format
msgid "the header ~a should not have the value ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:960
+#: src/scm/webid-oidc/errors.scm:1010
#, scheme-format
msgid "the header ~a should be present"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:963
+#: src/scm/webid-oidc/errors.scm:1013
#, scheme-format
msgid "the server response wasn't expected: ~s (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:969
+#: src/scm/webid-oidc/errors.scm:1019
#, scheme-format
msgid "the value ~s is not an OIDC configuration (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:974
+#: src/scm/webid-oidc/errors.scm:1024
#, scheme-format
msgid "the webid field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:975
+#: src/scm/webid-oidc/errors.scm:1025
msgid "the webid field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:979
+#: src/scm/webid-oidc/errors.scm:1029
#, scheme-format
msgid "the sub field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:980
+#: src/scm/webid-oidc/errors.scm:1030
msgid "the sub field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:984
+#: src/scm/webid-oidc/errors.scm:1034
#, scheme-format
msgid "the iss field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:985
+#: src/scm/webid-oidc/errors.scm:1035
msgid "the iss field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:989
+#: src/scm/webid-oidc/errors.scm:1039
#, scheme-format
msgid "the aud field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:990
+#: src/scm/webid-oidc/errors.scm:1040
msgid "the aud field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:994
+#: src/scm/webid-oidc/errors.scm:1044
#, scheme-format
msgid "the iat field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:995
+#: src/scm/webid-oidc/errors.scm:1045
msgid "the iat field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:999
+#: src/scm/webid-oidc/errors.scm:1049
#, scheme-format
msgid "the exp field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1000
+#: src/scm/webid-oidc/errors.scm:1050
msgid "the exp field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1004
+#: src/scm/webid-oidc/errors.scm:1054
#, scheme-format
msgid "the cnf/jkt field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1005
+#: src/scm/webid-oidc/errors.scm:1055
msgid "the cnf/jkt field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1009
+#: src/scm/webid-oidc/errors.scm:1059
#, scheme-format
msgid "the client-id field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1010
+#: src/scm/webid-oidc/errors.scm:1060
msgid "the client-id field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1014
+#: src/scm/webid-oidc/errors.scm:1064
#: src/scm/webid-oidc/authorization-page-unsafe.scm:133
#, scheme-format
msgid "the redirect_uris field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1015
+#: src/scm/webid-oidc/errors.scm:1065
#: src/scm/webid-oidc/authorization-page-unsafe.scm:134
msgid "the redirect_uris field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1019
+#: src/scm/webid-oidc/errors.scm:1069
#, scheme-format
msgid "the typ field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1020
+#: src/scm/webid-oidc/errors.scm:1070
msgid "the typ field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1024
+#: src/scm/webid-oidc/errors.scm:1074
#, scheme-format
msgid "the jwk field is incorrect: ~s (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1026
+#: src/scm/webid-oidc/errors.scm:1076
msgid "the jwk field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1030
+#: src/scm/webid-oidc/errors.scm:1080
#, scheme-format
msgid "the jti field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1031
+#: src/scm/webid-oidc/errors.scm:1081
msgid "the jti field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1035
+#: src/scm/webid-oidc/errors.scm:1085
#, scheme-format
msgid "the nonce field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1036
+#: src/scm/webid-oidc/errors.scm:1086
msgid "the nonce field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1040
+#: src/scm/webid-oidc/errors.scm:1090
#, scheme-format
msgid "the htm field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1041
+#: src/scm/webid-oidc/errors.scm:1091
msgid "the htm field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1045
+#: src/scm/webid-oidc/errors.scm:1095
#, scheme-format
msgid "the htu field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1046
+#: src/scm/webid-oidc/errors.scm:1096
msgid "the htu field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1048
+#: src/scm/webid-oidc/errors.scm:1098
#, scheme-format
msgid "~s is not an access token (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1051
+#: src/scm/webid-oidc/errors.scm:1101
#, scheme-format
msgid "~s is not an access token header (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1054
+#: src/scm/webid-oidc/errors.scm:1104
#, scheme-format
msgid "~s is not an access token payload (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1057
+#: src/scm/webid-oidc/errors.scm:1107
#, scheme-format
msgid "~s is not a DPoP proof (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1060
+#: src/scm/webid-oidc/errors.scm:1110
#, scheme-format
msgid "~s is not a DPoP proof header (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1063
+#: src/scm/webid-oidc/errors.scm:1113
#, scheme-format
msgid "~s is not a DPoP proof payload (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1066
+#: src/scm/webid-oidc/errors.scm:1116
#, scheme-format
msgid "I cannot fetch the issuer configuration of ~a (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1073
+#: src/scm/webid-oidc/errors.scm:1123
#, scheme-format
msgid "I cannot fetch the JWKS of ~a at ~a (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1084
+#: src/scm/webid-oidc/errors.scm:1134
#, scheme-format
msgid "the HTTP method is signed for ~s, but ~s was requested"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1087
+#: src/scm/webid-oidc/errors.scm:1137
#, scheme-format
msgid "the HTTP uri is signed for ~a, but ~a was requested"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1090
+#: src/scm/webid-oidc/errors.scm:1140
#, scheme-format
msgid "the date is ~a, but the DPoP proof is signed in the future at ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1094
+#: src/scm/webid-oidc/errors.scm:1144
#, scheme-format
msgid "the date is ~a, but the DPoP proof was signed too long ago at ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1103
+#: src/scm/webid-oidc/errors.scm:1153
#, scheme-format
msgid "the key ~s does not hash to ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1105
+#: src/scm/webid-oidc/errors.scm:1155
#, scheme-format
msgid "the key confirmation of ~s failed (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1107
+#: src/scm/webid-oidc/errors.scm:1157
#, scheme-format
msgid "the key confirmation of ~s failed"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1109
+#: src/scm/webid-oidc/errors.scm:1159
#, scheme-format
msgid "the jti ~s has already been found (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1112
+#: src/scm/webid-oidc/errors.scm:1162
#, scheme-format
msgid "I cannot decode ~s as an access token (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1115
+#: src/scm/webid-oidc/errors.scm:1165
#, scheme-format
msgid "I cannot encode ~s as an access token with key ~s (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1118
+#: src/scm/webid-oidc/errors.scm:1168
#, scheme-format
msgid "I cannot decode ~s as a DPoP proof (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1121
+#: src/scm/webid-oidc/errors.scm:1171
#, scheme-format
msgid "I cannot encode ~s as a DPoP proof (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1124
+#: src/scm/webid-oidc/errors.scm:1174
#, scheme-format
msgid "I could not fetch a RDF graph at ~a (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1127
+#: src/scm/webid-oidc/errors.scm:1177
#, scheme-format
msgid "~s is not a client manifest (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1130
+#: src/scm/webid-oidc/errors.scm:1180
#, scheme-format
msgid "~s does not authorize redirection URI ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1133
+#: src/scm/webid-oidc/errors.scm:1183
msgid "I cannot serve a public manifest"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1135
+#: src/scm/webid-oidc/errors.scm:1185
#, scheme-format
msgid "~a does not have a client manifest registration triple"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1138
+#: src/scm/webid-oidc/errors.scm:1188
#, scheme-format
msgid "the client manifest at ~a is advertised for ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1141
+#: src/scm/webid-oidc/errors.scm:1191
#, scheme-format
msgid "I could not fetch the client manifest of ~a (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1144
+#: src/scm/webid-oidc/errors.scm:1194
#, scheme-format
msgid "~s is not an authorization code (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1147
+#: src/scm/webid-oidc/errors.scm:1197
#, scheme-format
msgid "~s is not an authorization code header (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1150
+#: src/scm/webid-oidc/errors.scm:1200
#, scheme-format
msgid "~s is not an authorization code payload (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1153
+#: src/scm/webid-oidc/errors.scm:1203
#, scheme-format
msgid "the current time is ~a, and the authorization code expired at ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1157
+#: src/scm/webid-oidc/errors.scm:1207
#, scheme-format
msgid "I cannot decode ~s as an authorization code (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1160
+#: src/scm/webid-oidc/errors.scm:1210
#, scheme-format
msgid "I cannot encode ~s as an authorization code (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1163
+#: src/scm/webid-oidc/errors.scm:1213
#, scheme-format
msgid "there is no such refresh token as ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1166
+#: src/scm/webid-oidc/errors.scm:1216
#, scheme-format
msgid ""
"the refresh token is bound to a key confirmed as ~s, but it is used with key "
"~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1169
+#: src/scm/webid-oidc/errors.scm:1219
#, scheme-format
msgid "I cannot decode ~s as an ID token (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1172
+#: src/scm/webid-oidc/errors.scm:1222
#, scheme-format
msgid "I cannot encode ~s as an ID token (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1175
+#: src/scm/webid-oidc/errors.scm:1225
#, scheme-format
msgid "the grant type ~s is not supported"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1178
+#: src/scm/webid-oidc/errors.scm:1228
msgid "there is no authorization code in the request"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1180
+#: src/scm/webid-oidc/errors.scm:1230
msgid "there is no refresh token in the request"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1182
+#: src/scm/webid-oidc/errors.scm:1232
#, scheme-format
msgid "~s is not an ID token (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1185
+#: src/scm/webid-oidc/errors.scm:1235
#, scheme-format
msgid "~s is not an ID token header (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1188
+#: src/scm/webid-oidc/errors.scm:1238
#, scheme-format
msgid "~s is not an ID token payload (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1191
+#: src/scm/webid-oidc/errors.scm:1241
#, scheme-format
msgid ""
"I couldn’t set the locale to ~s as an approximation of the client locale ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1194
+#: src/scm/webid-oidc/errors.scm:1244
#, scheme-format
msgid "~s does not admit ~s as an identity provider"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1197
+#: src/scm/webid-oidc/errors.scm:1247
#, scheme-format
msgid ""
"~a is neither an identity provider (because ~a) nor a webid (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1202
+#: src/scm/webid-oidc/errors.scm:1252
#, scheme-format
msgid "the token request failed (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1205
+#: src/scm/webid-oidc/errors.scm:1255
#, scheme-format
msgid "you don’t have a refresh token for identity ~a certified by ~a in ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1210
+#: src/scm/webid-oidc/errors.scm:1260
#, scheme-format
msgid "all identity provider candidates for ~a failed: ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1214
+#: src/scm/webid-oidc/errors.scm:1264
#, scheme-format
msgid "~s failed (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1217
+#: src/scm/webid-oidc/errors.scm:1267
msgid ", "
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1221
+#: src/scm/webid-oidc/errors.scm:1269
+#, scheme-format
+msgid "no resource has been found to serve URI path ~s"
+msgstr ""
+
+#: src/scm/webid-oidc/errors.scm:1272
+#, scheme-format
+msgid "no resource has been found to serve URI path ~s, but ~s exists"
+msgstr ""
+
+#: src/scm/webid-oidc/errors.scm:1275
+msgid "the root storage cannot be deleted"
+msgstr ""
+
+#: src/scm/webid-oidc/errors.scm:1277
+#, scheme-format
+msgid "the container ~s should be emptied before being deleted"
+msgstr ""
+
+#: src/scm/webid-oidc/errors.scm:1282
msgid "that’s it"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1225
+#: src/scm/webid-oidc/errors.scm:1286
#, scheme-format
msgid "~a and ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1228
+#: src/scm/webid-oidc/errors.scm:1289
#, scheme-format
msgid "~a, ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1232
+#: src/scm/webid-oidc/errors.scm:1293
#, scheme-format
msgid "the signature ~a does not match key ~s with payload ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1235
+#: src/scm/webid-oidc/errors.scm:1296
msgid "there is an undefined variable"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1237
+#: src/scm/webid-oidc/errors.scm:1298
#, scheme-format
msgid "the origin is ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1240
+#: src/scm/webid-oidc/errors.scm:1301
#, scheme-format
msgid "a message is attached: ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1243
+#: src/scm/webid-oidc/errors.scm:1304
#, scheme-format
msgid "the values ~s are problematic"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1246
+#: src/scm/webid-oidc/errors.scm:1307
msgid "there is a kind and args"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1248
+#: src/scm/webid-oidc/errors.scm:1309
msgid "there is an assertion failure"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1250
+#: src/scm/webid-oidc/errors.scm:1311
#, scheme-format
msgid "the program quits with code ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1253
+#: src/scm/webid-oidc/errors.scm:1314
msgid "the program cannot recover from this exception"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1255
+#: src/scm/webid-oidc/errors.scm:1316
msgid "there is an error"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1257
+#: src/scm/webid-oidc/errors.scm:1318
#, scheme-format
msgid "Unhandled exception type ~a."
msgstr ""
diff --git a/src/scm/webid-oidc/errors.scm b/src/scm/webid-oidc/errors.scm
index 52f5db8..60e45f7 100644
--- a/src/scm/webid-oidc/errors.scm
+++ b/src/scm/webid-oidc/errors.scm
@@ -870,6 +870,56 @@
(raise-exception
((record-constructor &no-provider-candidates) webid causes)))
+;; Server-side exceptions
+
+(define-exception-type
+ &path-not-found
+ &external-error
+ make-path-not-found
+ path-not-found?
+ (path path-not-found-path))
+
+(export &path-not-found
+ make-path-not-found
+ path-not-found?
+ path-not-found-path)
+
+(define-exception-type
+ &uri-slash-semantics-error
+ &external-error
+ make-uri-slash-semantics-error
+ uri-slash-semantics-error?
+ (path uri-slash-semantics-error-path)
+ (expected-path uri-slash-semantics-error-expected-path))
+
+(export &uri-slash-semantics-error
+ make-uri-slash-semantics-error
+ uri-slash-semantics-error?
+ uri-slash-semantics-error-path
+ uri-slash-semantics-error-expected-path)
+
+(define-exception-type
+ &cannot-delete-root
+ &external-error
+ make-cannot-delete-root
+ cannot-delete-root?)
+
+(export &cannot-delete-root
+ make-cannot-delete-root
+ cannot-delete-root?)
+
+(define-exception-type
+ &container-not-empty
+ &external-error
+ make-container-not-empty
+ container-not-empty?
+ (path container-not-empty-path))
+
+(export &container-not-empty
+ make-container-not-empty
+ container-not-empty?
+ container-not-empty-path)
+
(define*-public (error->str err #:key (max-depth #f))
(if (record? err)
(let* ((type (record-type-descriptor err))
@@ -1193,28 +1243,39 @@
((&unconfirmed-provider)
(format #f (G_ "~s does not admit ~s as an identity provider")
(get 'subject) (get 'provider)))
- ((&neither-identity-provider-nor-webid)
- (format #f (G_ "~a is neither an identity provider (because ~a) nor a webid (because ~a)")
- (uri->string (get 'uri))
- (recurse (get 'why-not-identity-provider))
- (recurse (get 'why-not-webid))))
- ((&token-request-failed)
- (format #f (G_ "the token request failed (because ~a)")
- (recurse (get 'cause))))
- ((&profile-not-found)
- (format #f (G_ "you don’t have a refresh token for identity ~a certified by ~a in ~s")
- (uri->string (get 'webid))
- (uri->string (get 'iss))
- (get 'dir)))
- ((&no-provider-candidates)
- (format #f (G_ "all identity provider candidates for ~a failed: ~a")
- (uri->string (get 'webid))
- (string-join
- (map (lambda (cause)
- (format #f (G_ "~s failed (because ~a)")
- (uri->string (car cause)) (recurse (cdr cause))))
- (get 'causes))
- (G_ ", "))))
+ ((&neither-identity-provider-nor-webid)
+ (format #f (G_ "~a is neither an identity provider (because ~a) nor a webid (because ~a)")
+ (uri->string (get 'uri))
+ (recurse (get 'why-not-identity-provider))
+ (recurse (get 'why-not-webid))))
+ ((&token-request-failed)
+ (format #f (G_ "the token request failed (because ~a)")
+ (recurse (get 'cause))))
+ ((&profile-not-found)
+ (format #f (G_ "you don’t have a refresh token for identity ~a certified by ~a in ~s")
+ (uri->string (get 'webid))
+ (uri->string (get 'iss))
+ (get 'dir)))
+ ((&no-provider-candidates)
+ (format #f (G_ "all identity provider candidates for ~a failed: ~a")
+ (uri->string (get 'webid))
+ (string-join
+ (map (lambda (cause)
+ (format #f (G_ "~s failed (because ~a)")
+ (uri->string (car cause)) (recurse (cdr cause))))
+ (get 'causes))
+ (G_ ", "))))
+ ((&path-not-found)
+ (format #f (G_ "no resource has been found to serve URI path ~s")
+ (get 'path)))
+ ((&uri-slash-semantics-error)
+ (format #f (G_ "no resource has been found to serve URI path ~s, but ~s exists")
+ (get 'path) (get 'expected-path)))
+ ((&cannot-delete-root)
+ (format #f (G_ "the root storage cannot be deleted")))
+ ((&container-not-empty)
+ (format #f (G_ "the container ~s should be emptied before being deleted")
+ (get 'path)))
((&compound-exception)
(let ((components (get 'components)))
(if (null? components)
diff --git a/src/scm/webid-oidc/server/resource/Makefile.am b/src/scm/webid-oidc/server/resource/Makefile.am
index 88103cc..49cc912 100644
--- a/src/scm/webid-oidc/server/resource/Makefile.am
+++ b/src/scm/webid-oidc/server/resource/Makefile.am
@@ -1,5 +1,7 @@
dist_resourceserverwebidoidcmod_DATA += \
- %reldir%/content.scm
+ %reldir%/content.scm \
+ %reldir%/path.scm
resourceserverwebidoidcgo_DATA += \
- %reldir%/content.go
+ %reldir%/content.go \
+ %reldir%/path.go
diff --git a/src/scm/webid-oidc/server/resource/path.scm b/src/scm/webid-oidc/server/resource/path.scm
new file mode 100644
index 0000000..a637d60
--- /dev/null
+++ b/src/scm/webid-oidc/server/resource/path.scm
@@ -0,0 +1,185 @@
+(define-module (webid-oidc server resource path)
+ #:use-module (webid-oidc errors)
+ #:use-module ((webid-oidc stubs) #:prefix stubs:)
+ #:use-module (webid-oidc rdf-index)
+ #:use-module ((webid-oidc refresh-token) #:prefix refresh:)
+ #:use-module (web uri)
+ #:use-module (rnrs bytevectors)
+ #:use-module (ice-9 exceptions)
+ #:use-module (ice-9 receive)
+ #:use-module (ice-9 optargs)
+ #:use-module (ice-9 iconv)
+ #:use-module (ice-9 textual-ports)
+ #:use-module (ice-9 binary-ports)
+ #:use-module (ice-9 threads)
+ #:use-module (rnrs bytevectors)
+ #:use-module (oop goops)
+ #:export
+ (
+
+ read-path
+ update-path
+
+ ))
+
+(define (default-dir)
+ (string-append (refresh:default-dir) "/server"))
+
+(define (hash-path path)
+ (let ((h (stubs:hash 'SHA-256 path))
+ (dir (default-dir)))
+ (let ((first-char (substring h 0 1))
+ (rest (substring h 1)))
+ (format #f "~a/path/~a/~a" dir first-char rest))))
+
+(define (read-path path)
+ (let ((h (hash-path path)))
+ (with-exception-handler
+ (lambda (error)
+ (let ((with-slash (string-append path "/"))
+ (without-slash
+ (if (string-suffix? "/" path)
+ (substring path 0 (- (string-length path) (string-length "/")))
+ path)))
+ (let ((with-slash-exists (file-exists? (hash-path with-slash)))
+ (without-slash-exists (file-exists? (hash-path without-slash))))
+ (cond
+ (with-slash-exists
+ (raise-exception
+ (make-exception
+ (make-path-not-found path)
+ (make-uri-slash-semantics-error path with-slash))))
+ (without-slash-exists
+ (raise-exception
+ (make-exception
+ (make-path-not-found path)
+ (make-uri-slash-semantics-error path with-slash))))
+ (else
+ (raise-exception (make-path-not-found path)))))))
+ (lambda ()
+ (call-with-input-file h
+ (lambda (port)
+ (let ((main-etag (read port)))
+ (let ((auxiliary (read port)))
+ (values main-etag
+ (map (lambda (cell)
+ (let ((key (string->uri (car cell)))
+ (value (string->uri (cdr cell))))
+ (cons key value)))
+ auxiliary))))))))))
+
+(define* (update-path path f content-type contained static-content create delete
+ #:key (create-intermediate-containers? #f))
+ (let ((h (hash-path path))
+ (garbage (make-hash-table))
+ (has-been-created? #f)
+ (has-been-deleted? #f)
+ (parent-path
+ (let ((components (split-and-decode-uri-path path)))
+ (cond
+ ((null? components)
+ #f)
+ ((null? (cdr components))
+ "/")
+ (else
+ (string-append
+ "/"
+ (encode-and-join-uri-path
+ (reverse
+ (cdr
+ (reverse components))))
+ "/"))))))
+ (stubs:atomically-update-file
+ h
+ (lambda (port)
+ (receive (etag auxiliary)
+ (with-exception-handler
+ (lambda (error)
+ (unless (path-not-found? error)
+ (raise-exception error))
+ (set! has-been-created? #t)
+ (values #f #f))
+ (lambda ()
+ (read-path path))
+ #:unwind? #t
+ #:unwind-for-type &path-not-found)
+ (when etag
+ (hash-set! garbage etag #t))
+ (when auxiliary
+ (for-each
+ (lambda (cell)
+ (when (cdr cell)
+ (hash-set! garbage (cdr cell) #t)))
+ auxiliary))
+ (call-with-values
+ (lambda ()
+ (f etag auxiliary))
+ (case-lambda
+ ((false)
+ (when false
+ (error "You’re using the API wrong."))
+ ;; Delete the resource
+ (unless (null? (contained etag))
+ (raise-exception (make-container-not-empty path)))
+ (when (equal? path "/")
+ (raise-exception (make-cannot-delete-root)))
+ (set! has-been-deleted? #t)
+ #f)
+ ((new-etag new-auxiliary)
+ (unless (and (string? new-etag) (list? new-auxiliary))
+ (error "You’re using the API wrong."))
+ (hash-remove! garbage new-etag)
+ (when new-auxiliary
+ (for-each
+ (lambda (cell)
+ (hash-remove! garbage (cdr cell)))
+ new-auxiliary))
+ (write new-etag port)
+ (write (map (lambda (cell)
+ (cons (uri->string (car cell))
+ (cdr cell)))
+ new-auxiliary)
+ port)
+ #t))))))
+ (when (and parent-path has-been-created? (not has-been-deleted?))
+ (update-path
+ parent-path
+ (lambda (etag auxiliary)
+ ;; Add path as a child of the resource at etag
+ (unless create-intermediate-containers?
+ (unless etag
+ ;; Typically, POST to a non-existing path
+ (raise-exception (make-path-not-found parent-path))))
+ (unless auxiliary
+ (set! auxiliary '()))
+ (let ((content-type (if etag (content-type etag) 'text/turtle))
+ (other-children (if etag (contained etag) '()))
+ (static-content (if etag (static-content etag) (string->utf8 ""))))
+ (unless (eq? content-type 'text/turtle)
+ (raise-exception (make-not-a-container parent-path content-type)))
+ (let ((new-etag
+ (create content-type (cons path other-children) static-content)))
+ (values new-etag auxiliary))))
+ content-type contained static-content create delete
+ #:create-intermediate-containers? create-intermediate-containers?))
+ (when (and parent-path has-been-deleted? (not has-been-created?))
+ (update-path
+ parent-path
+ (lambda (etag auxiliary)
+ (unless etag
+ (raise-exception (make-path-not-found parent-path)))
+ (let ((content-type (content-type etag))
+ (all-children (contained etag))
+ (static-content (static-content etag)))
+ (values
+ (create content-type
+ (filter (lambda (x)
+ (not (equal? x path)))
+ all-children)
+ static-content)
+ auxiliary)))
+ content-type contained static-content create delete
+ #:create-intermediate-containers? create-intermediate-containers?))
+ (for-each
+ delete
+ (hash-map->list (lambda (garbage false) garbage) garbage))))
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 14101ea..17aa6f4 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -41,7 +41,8 @@ TESTS = %reldir%/load-library.scm \
%reldir%/client-authorization.scm \
%reldir%/client-token.scm \
%reldir%/client-manifest-not-modified.scm \
- %reldir%/server-content.scm
+ %reldir%/server-content.scm \
+ %reldir%/server-path.scm
EXTRA_DIST += $(TESTS) %reldir%/ChangeLog
diff --git a/tests/server-path.scm b/tests/server-path.scm
new file mode 100644
index 0000000..f45fb38
--- /dev/null
+++ b/tests/server-path.scm
@@ -0,0 +1,151 @@
+(use-modules (webid-oidc server resource content)
+ (webid-oidc server resource path)
+ (webid-oidc fetch)
+ (webid-oidc testing)
+ (webid-oidc errors)
+ (web uri)
+ (web response)
+ (rnrs bytevectors)
+ (ice-9 optargs)
+ (ice-9 receive)
+ (oop goops))
+
+(with-test-environment
+ "server-path"
+ (lambda ()
+ (for-each
+ (lambda (file)
+ (false-if-exception (delete-file file)))
+ '(
+ "tests/server-path.home/webid-oidc/server/content/6/8OMG_V5x-KmI6TI"
+ "tests/server-path.home/webid-oidc/server/content/X/hqM_2Avn5_egTzs"
+ "tests/server-path.home/webid-oidc/server/content/a/68pTwiImTWTpjQl"
+ "tests/server-path.home/webid-oidc/server/content/5/n1KPgAd3ng4wSqn"
+ "tests/server-path.home/webid-oidc/server/content/D/wxU0ogx5rzRrvu2"
+ "tests/server-path.home/webid-oidc/server/content/F/BQKBGrtq6U_M0L7"
+ "tests/server-path.home/webid-oidc/server/content/N/gnO8RAS9FpPiO5j"
+ "tests/server-path.home/webid-oidc/server/content/n/U46BXbknEaLWZpH"
+ "tests/server-path.home/webid-oidc/server/content/y/29x0MEOMybxUqDU"
+ "tests/server-path.home/webid-oidc/server/content/b/k7RqZevpCHAumba"
+ "tests/server-path.home/webid-oidc/server/content/H/y4S5p1BqTEJi-Jb"
+ "tests/server-path.home/webid-oidc/server/content/A/fkGTJRCHc-jHk-V"
+ "tests/server-path.home/webid-oidc/server/path/b/FkceBVDI7O39t4bFK02Vu0E7OWtjnjDfAXDLKuREbE"
+ "tests/server-path.home/webid-oidc/server/path/b/FkceBVDI7O39t4bFK02Vu0E7OWtjnjDfAXDLKuREbE.lock"
+ "tests/server-path.home/webid-oidc/server/path/g/pBBL3msK7bpJ_LUp4xDyrB-EZD1EaJgD6xo9ysqy6Q"
+ "tests/server-path.home/webid-oidc/server/path/g/pBBL3msK7bpJ_LUp4xDyrB-EZD1EaJgD6xo9ysqy6Q.lock"
+ "tests/server-path.home/webid-oidc/server/path/i/l7asoJjJEMhngUeSt4tHVu8Zxx4EFG_FDeJfL3-oPE"
+ "tests/server-path.home/webid-oidc/server/path/i/l7asoJjJEMhngUeSt4tHVu8Zxx4EFG_FDeJfL3-oPE.lock"
+ "tests/server-path.home/webid-oidc/server/path/Q/hRrKeOf3iJxfvabWz2CBYAlF_ovDFXqHWcwhhuQhXg"
+ "tests/server-path.home/webid-oidc/server/path/Q/hRrKeOf3iJxfvabWz2CBYAlF_ovDFXqHWcwhhuQhXg.lock"
+ ))
+ (with-session
+ (lambda (content-type contained static-content create delete)
+ (let ((new-etag
+ (lambda ()
+ (create 'text/plain '() "Hello :)")))
+ (new-acl
+ (lambda ()
+ (create 'text/turtle '()
+ "@prefix acl: <http://www.w3.org/ns/auth/acl#>.
+
+<#authorized> a acl:Authorization;
+ acl:accessTo <https://example.com/a/b/c>;
+ acl:mode acl:Read;
+ acl:agent <https://friend.example.com/profile/card#me>.
+"))))
+ ;; Create with parents:
+ (update-path
+ "/a/b/c"
+ (lambda (etag auxiliary)
+ (when (or etag auxiliary)
+ (exit 1))
+ (values (new-etag) `((,(string->uri "http://www.w3.org/ns/auth/acl#accessControl") . ,(new-acl)))))
+ content-type contained static-content create delete
+ #:create-intermediate-containers? #t)
+ ;; So now, there should be a chain of directories:
+ (receive (root-etag root-aux)
+ (read-path "/")
+ (let ((root-children (contained root-etag)))
+ (unless (equal? root-children '("/a/"))
+ (exit 2)))
+ (unless (null? root-aux)
+ (exit 3)))
+ (receive (/a/ /a/-aux)
+ (read-path "/a/")
+ (unless (equal? (contained /a/) '("/a/b/"))
+ (exit 4))
+ (unless (null? /a/-aux)
+ (exit 5)))
+ (receive (/a/b/ /a/b/-aux)
+ (read-path "/a/b/")
+ (unless (equal? (contained /a/b/) '("/a/b/c"))
+ (exit 6))
+ (unless (null? /a/b/-aux)
+ (exit 7)))
+ (receive (/a/b/c /a/b/c-aux)
+ (read-path "/a/b/c")
+ (unless (equal? (content-type /a/b/c) 'text/plain)
+ (exit 8))
+ (unless (equal? (static-content /a/b/c)
+ (string->utf8 "Hello :)"))
+ (exit 9)))
+ ;; We can delete /a/b/c
+ (update-path "/a/b/c" (lambda (etag aux) #f)
+ content-type contained static-content create delete)
+ ;; Now /a/b/c does not exist
+ (with-exception-handler
+ (lambda (error)
+ (unless (path-not-found? error)
+ (exit 10)))
+ (lambda ()
+ (read-path "/a/b/c")
+ (exit 11))
+ #:unwind? #t
+ #:unwind-for-type &path-not-found)
+ ;; We can’t delete /a/ because there's /a/b/ in it
+ (with-exception-handler
+ (lambda (error)
+ (unless (container-not-empty? error)
+ (exit 12))
+ (unless (equal? (container-not-empty-path error) "/a/")
+ (exit 13)))
+ (lambda ()
+ (update-path "/a/" (lambda (etag aux) #f)
+ content-type contained static-content create delete)
+ (exit 14))
+ #:unwind? #t
+ #:unwind-for-type &container-not-empty)
+ ;; However, we can recreate /a/b/c without creating intermediate containers
+ (update-path "/a/b/c"
+ (lambda (etag aux)
+ (values (new-etag)
+ `((,(string->uri
+ "http://www.w3.org/ns/auth/acl#accessControl")
+ . ,(new-acl)))))
+ content-type contained static-content create delete
+ #:create-intermediate-containers? #f)
+ ;; Delete /a/b/c again
+ (update-path "/a/b/c" (lambda (etag aux) #f)
+ content-type contained static-content create delete)
+ ;; Delete /a/b/
+ (update-path "/a/b/" (lambda (etag aux) #f)
+ content-type contained static-content create delete)
+ ;; Delete /a/
+ (update-path "/a/" (lambda (etag aux) #f)
+ content-type contained static-content create delete)
+ ;; Cannot delete the root
+ (with-exception-handler
+ (lambda (error)
+ (unless (cannot-delete-root? error)
+ (exit 15)))
+ (lambda ()
+ (update-path "/" (lambda (etag aux) #f)
+ content-type contained static-content create delete)
+ (exit 16))
+ #:unwind? #t
+ #:unwind-for-type &cannot-delete-root)
+ ;; However, the root should be empty
+ (receive (root-etag root-aux)
+ (read-path "/")
+ (unless (null? (contained root-etag))
+ (exit 17))))))))