From 4597ca12db7ced1217f459e68a20bd6766e4a902 Mon Sep 17 00:00:00 2001 From: Vivien Kraus Date: Thu, 3 Jun 2021 18:16:10 +0200 Subject: Add an API to update server resource paths --- doc/webid-oidc.texi | 98 +++++++++ po/fr.po | 284 +++++++++++++------------ po/webid-oidc.pot | 265 ++++++++++++----------- src/scm/webid-oidc/errors.scm | 105 +++++++-- src/scm/webid-oidc/server/resource/Makefile.am | 6 +- src/scm/webid-oidc/server/resource/path.scm | 185 ++++++++++++++++ tests/Makefile.am | 3 +- tests/server-path.scm | 151 +++++++++++++ 8 files changed, 809 insertions(+), 288 deletions(-) create mode 100644 src/scm/webid-oidc/server/resource/path.scm create mode 100644 tests/server-path.scm 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} ¬-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 \n" "Language-Team: French \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 \n" "Language-Team: LANGUAGE \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: . + +<#authorized> a acl:Authorization; + acl:accessTo ; + acl:mode acl:Read; + acl:agent . +")))) + ;; 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)))))))) -- cgit v1.2.3