summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVivien Kraus <vivien@planete-kraus.eu>2021-05-17 22:39:03 +0200
committerVivien Kraus <vivien@planete-kraus.eu>2021-05-18 00:49:21 +0200
commita8cc0aba66c9f25693d2c58787a6e24199e50af1 (patch)
tree1ff2095b57cd87268354afde7fa26ca9eb0d7a68
parent1a52b8abb4ee98406d33c45eff5de9f6ca360bea (diff)
Load and save resources for the server
-rw-r--r--po/fr.po282
-rw-r--r--po/webid-oidc.pot277
-rw-r--r--src/Makefile.am15
-rw-r--r--src/scm/webid-oidc/Makefile.am2
-rw-r--r--src/scm/webid-oidc/errors.scm118
-rw-r--r--src/scm/webid-oidc/server/Makefile.am5
-rw-r--r--src/scm/webid-oidc/server/resource.scm186
-rw-r--r--tests/Makefile.am11
-rw-r--r--tests/server-create-resource.scm33
-rw-r--r--tests/server-prevent-concurrent-creation.scm51
-rw-r--r--tests/server-prevent-concurrent-delete.scm28
-rw-r--r--tests/server-prevent-concurrent-update-and-delete.scm42
-rw-r--r--tests/server-prevent-concurrent-update.scm51
-rw-r--r--tests/server-read-non-existing-resource.scm19
-rw-r--r--tests/server-read-resource.scm49
-rw-r--r--tests/server-update-if-none-match.scm53
-rw-r--r--tests/server-update-resource.scm53
17 files changed, 1001 insertions, 274 deletions
diff --git a/po/fr.po b/po/fr.po
index 157573b..9cfd8be 100644
--- a/po/fr.po
+++ b/po/fr.po
@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: webid-oidc 0.0.0\n"
"Report-Msgid-Bugs-To: vivien@planete-kraus.eu\n"
-"POT-Creation-Date: 2021-05-12 18:02+0200\n"
-"PO-Revision-Date: 2021-05-10 23:12+0200\n"
+"POT-Creation-Date: 2021-05-18 00:33+0200\n"
+"PO-Revision-Date: 2021-05-18 00:35+0200\n"
"Last-Translator: Vivien Kraus <vivien@planete-kraus.eu>\n"
"Language-Team: French <vivien@planete-kraus.eu>\n"
"Language: fr\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:937
msgid "that’s how it is"
msgstr "c’est comme ça"
-#: src/scm/webid-oidc/errors.scm:886
+#: src/scm/webid-oidc/errors.scm:942
#, 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:945
#, 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:948
#, 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:951
#, 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:956
#, 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:958
#, 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:963
#, 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:965
#, 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:970
#, 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:972
#, 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:977
#, 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:979
#, 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:982
#, 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:985
#, 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:988
#, 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:991
#, 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:994
#, 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:997
#, 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:1000
#, 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:1003
#, 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:1006
#, 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:1009
#, scheme-format
msgid ""
"the server request unexpectedly failed with code ~a and reason phrase ~s"
@@ -247,336 +247,336 @@ 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:1014
#, 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:1016
#, 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:1019
#, 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:1025
#, 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:1030
#, 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:1031
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:1035
#, 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:1036
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:1040
#, 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:1041
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:1045
#, 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:1046
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:1050
#, 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:1051
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:1055
#, 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:1056
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:1060
#, 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:1061
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:1065
#, 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:1066
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:1070
#: src/scm/webid-oidc/authorization-page-unsafe.scm:132
#, 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:1071
#: src/scm/webid-oidc/authorization-page-unsafe.scm:133
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:1075
#, 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:1076
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:1080
#, 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:1082
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:1086
#, 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:1087
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:1091
#, 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:1092
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:1096
#, 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:1097
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:1101
#, 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:1102
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:1104
#, 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:1107
#, 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:1110
#, 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:1113
#, 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:1116
#, 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:1119
#, 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:1122
#, 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:1129
#, 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:1140
#, 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:1143
#, 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:1146
#, 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:1150
#, 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:1159
#, 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:1161
#, 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:1163
#, 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:1165
#, 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:1168
#, 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:1171
#, scheme-format
msgid "I cannot encode ~s as an access token (because ~a)"
msgstr "je n’ai pas pu encoder ~s comme un jeton d’accès (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:1118
+#: src/scm/webid-oidc/errors.scm:1174
#, 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:1177
#, 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:1180
#, 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:1183
#, 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:1186
#, 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:1189
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:1191
#, 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:1194
#, 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:1197
#, 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:1200
#, 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:1203
#, 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:1206
#, 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:1209
#, 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:1213
#, 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:1216
#, 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:1219
#, 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:1222
#, scheme-format
msgid ""
"the refresh token is bound to a key confirmed as ~s, but it is used with key "
@@ -585,45 +585,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:1225
#, 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:1228
#, 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:1231
#, 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:1234
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:1236
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:1238
#, 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:1241
#, 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:1244
#, 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:1247
#, scheme-format
msgid ""
"I couldn’t set the locale to ~s as an approximation of the client locale ~s"
@@ -631,12 +631,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:1250
#, 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:1253
#, scheme-format
msgid ""
"~a is neither an identity provider (because ~a) nor a webid (because ~a)"
@@ -644,92 +644,126 @@ 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:1258
#, 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:1261
#, 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:1266
#, 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:1270
#, 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:1273
msgid ", "
msgstr ", "
-#: src/scm/webid-oidc/errors.scm:1221
+#: src/scm/webid-oidc/errors.scm:1275
+#, scheme-format
+msgid "the resource ~s could not be found (because ~a)"
+msgstr "la ressource ~s n’a pas été trouvée (parce que ~a)"
+
+#: src/scm/webid-oidc/errors.scm:1279
+#, scheme-format
+msgid "the resource is missing an etag (see ~s)"
+msgstr "la ressource n’a pas d’etag (voir ~s)"
+
+#: src/scm/webid-oidc/errors.scm:1282
+#, scheme-format
+msgid "the resource is missing a content type (see ~s)"
+msgstr "la ressource n’a pas de type de contenu (voir ~s)"
+
+#: src/scm/webid-oidc/errors.scm:1286
+#, scheme-format
+msgid "the precondition failed for etag ~s: if-match ~s and if-none-match ~s"
+msgstr ""
+"la pré-condition a échoué pour l’etag ~s : if-match ~s et if-none-match ~s"
+
+#: src/scm/webid-oidc/errors.scm:1288
+#, scheme-format
+msgid ""
+"the precondition failed for a non-existing resource: if-match ~s and if-none-"
+"match ~s"
+msgstr ""
+"la précondition a échoué pour une ressource inexistante : if-match ~s et if-"
+"none-match ~s"
+
+#: src/scm/webid-oidc/errors.scm:1293
msgid "that’s it"
msgstr "c’est tout"
-#: src/scm/webid-oidc/errors.scm:1225
+#: src/scm/webid-oidc/errors.scm:1297
#, scheme-format
msgid "~a and ~a"
msgstr "~a et ~a"
-#: src/scm/webid-oidc/errors.scm:1228
+#: src/scm/webid-oidc/errors.scm:1300
#, scheme-format
msgid "~a, ~a"
msgstr "~a, ~a"
-#: src/scm/webid-oidc/errors.scm:1232
+#: src/scm/webid-oidc/errors.scm:1304
#, 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:1307
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:1309
#, 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:1312
#, 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:1315
#, 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:1318
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:1320
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:1322
#, 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:1325
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:1327
msgid "there is an error"
msgstr "il y a une erreur"
-#: src/scm/webid-oidc/errors.scm:1257
+#: src/scm/webid-oidc/errors.scm:1329
+msgid "there is an external error"
+msgstr "il y a une erreur externe"
+
+#: src/scm/webid-oidc/errors.scm:1331
#, scheme-format
msgid "Unhandled exception type ~a."
msgstr "Type d’exception non pris en charge ~a."
diff --git a/po/webid-oidc.pot b/po/webid-oidc.pot
index 3401528..926dd70 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-05-12 18:02+0200\n"
+"POT-Creation-Date: 2021-05-18 00:33+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,626 @@ msgstr ""
msgid "Usage: generate-key [NUMBER OF BITS | CURVE]\n"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:881
+#: src/scm/webid-oidc/errors.scm:937
msgid "that’s how it is"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:886
+#: src/scm/webid-oidc/errors.scm:942
#, 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:945
#, 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:948
#, 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:951
#, 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:956
#, 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:958
#, 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:963
#, 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:965
#, 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:970
#, 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:972
#, 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:977
#, 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:979
#, 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:982
#, 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:985
#, 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:988
#, 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:991
#, 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:994
#, 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:997
#, 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:1000
#, 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:1003
#, scheme-format
msgid "I cannot decode JWS ~a (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:950
+#: src/scm/webid-oidc/errors.scm:1006
#, scheme-format
msgid "I cannot encode JWS ~a (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:953
+#: src/scm/webid-oidc/errors.scm:1009
#, 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:1014
#, 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:1016
#, scheme-format
msgid "the header ~a should be present"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:963
+#: src/scm/webid-oidc/errors.scm:1019
#, 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:1025
#, 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:1030
#, scheme-format
msgid "the webid field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:975
+#: src/scm/webid-oidc/errors.scm:1031
msgid "the webid field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:979
+#: src/scm/webid-oidc/errors.scm:1035
#, scheme-format
msgid "the sub field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:980
+#: src/scm/webid-oidc/errors.scm:1036
msgid "the sub field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:984
+#: src/scm/webid-oidc/errors.scm:1040
#, scheme-format
msgid "the iss field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:985
+#: src/scm/webid-oidc/errors.scm:1041
msgid "the iss field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:989
+#: src/scm/webid-oidc/errors.scm:1045
#, scheme-format
msgid "the aud field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:990
+#: src/scm/webid-oidc/errors.scm:1046
msgid "the aud field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:994
+#: src/scm/webid-oidc/errors.scm:1050
#, scheme-format
msgid "the iat field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:995
+#: src/scm/webid-oidc/errors.scm:1051
msgid "the iat field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:999
+#: src/scm/webid-oidc/errors.scm:1055
#, scheme-format
msgid "the exp field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1000
+#: src/scm/webid-oidc/errors.scm:1056
msgid "the exp field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1004
+#: src/scm/webid-oidc/errors.scm:1060
#, scheme-format
msgid "the cnf/jkt field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1005
+#: src/scm/webid-oidc/errors.scm:1061
msgid "the cnf/jkt field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1009
+#: src/scm/webid-oidc/errors.scm:1065
#, scheme-format
msgid "the client-id field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1010
+#: src/scm/webid-oidc/errors.scm:1066
msgid "the client-id field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1014
+#: src/scm/webid-oidc/errors.scm:1070
#: src/scm/webid-oidc/authorization-page-unsafe.scm:132
#, scheme-format
msgid "the redirect_uris field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1015
+#: src/scm/webid-oidc/errors.scm:1071
#: src/scm/webid-oidc/authorization-page-unsafe.scm:133
msgid "the redirect_uris field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1019
+#: src/scm/webid-oidc/errors.scm:1075
#, scheme-format
msgid "the typ field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1020
+#: src/scm/webid-oidc/errors.scm:1076
msgid "the typ field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1024
+#: src/scm/webid-oidc/errors.scm:1080
#, 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:1082
msgid "the jwk field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1030
+#: src/scm/webid-oidc/errors.scm:1086
#, scheme-format
msgid "the jti field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1031
+#: src/scm/webid-oidc/errors.scm:1087
msgid "the jti field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1035
+#: src/scm/webid-oidc/errors.scm:1091
#, scheme-format
msgid "the nonce field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1036
+#: src/scm/webid-oidc/errors.scm:1092
msgid "the nonce field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1040
+#: src/scm/webid-oidc/errors.scm:1096
#, scheme-format
msgid "the htm field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1041
+#: src/scm/webid-oidc/errors.scm:1097
msgid "the htm field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1045
+#: src/scm/webid-oidc/errors.scm:1101
#, scheme-format
msgid "the htu field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1046
+#: src/scm/webid-oidc/errors.scm:1102
msgid "the htu field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1048
+#: src/scm/webid-oidc/errors.scm:1104
#, 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:1107
#, 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:1110
#, 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:1113
#, 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:1116
#, 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:1119
#, 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:1122
#, 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:1129
#, 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:1140
#, 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:1143
#, 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:1146
#, 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:1150
#, 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:1159
#, 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:1161
#, 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:1163
#, scheme-format
msgid "the key confirmation of ~s failed"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1109
+#: src/scm/webid-oidc/errors.scm:1165
#, 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:1168
#, 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:1171
#, scheme-format
msgid "I cannot encode ~s as an access token (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1118
+#: src/scm/webid-oidc/errors.scm:1174
#, 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:1177
#, 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:1180
#, 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:1183
#, 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:1186
#, scheme-format
msgid "~s does not authorize redirection URI ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1133
+#: src/scm/webid-oidc/errors.scm:1189
msgid "I cannot serve a public manifest"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1135
+#: src/scm/webid-oidc/errors.scm:1191
#, 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:1194
#, 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:1197
#, 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:1200
#, 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:1203
#, 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:1206
#, 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:1209
#, 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:1213
#, 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:1216
#, 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:1219
#, 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:1222
#, 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:1225
#, 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:1228
#, 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:1231
#, scheme-format
msgid "the grant type ~s is not supported"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1178
+#: src/scm/webid-oidc/errors.scm:1234
msgid "there is no authorization code in the request"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1180
+#: src/scm/webid-oidc/errors.scm:1236
msgid "there is no refresh token in the request"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1182
+#: src/scm/webid-oidc/errors.scm:1238
#, 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:1241
#, 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:1244
#, 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:1247
#, 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:1250
#, 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:1253
#, 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:1258
#, scheme-format
msgid "the token request failed (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1205
+#: src/scm/webid-oidc/errors.scm:1261
#, 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:1266
#, 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:1270
#, scheme-format
msgid "~s failed (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1217
+#: src/scm/webid-oidc/errors.scm:1273
msgid ", "
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1221
+#: src/scm/webid-oidc/errors.scm:1275
+#, scheme-format
+msgid "the resource ~s could not be found (because ~a)"
+msgstr ""
+
+#: src/scm/webid-oidc/errors.scm:1279
+#, scheme-format
+msgid "the resource is missing an etag (see ~s)"
+msgstr ""
+
+#: src/scm/webid-oidc/errors.scm:1282
+#, scheme-format
+msgid "the resource is missing a content type (see ~s)"
+msgstr ""
+
+#: src/scm/webid-oidc/errors.scm:1286
+#, scheme-format
+msgid "the precondition failed for etag ~s: if-match ~s and if-none-match ~s"
+msgstr ""
+
+#: src/scm/webid-oidc/errors.scm:1288
+#, scheme-format
+msgid ""
+"the precondition failed for a non-existing resource: if-match ~s and if-none-"
+"match ~s"
+msgstr ""
+
+#: src/scm/webid-oidc/errors.scm:1293
msgid "that’s it"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1225
+#: src/scm/webid-oidc/errors.scm:1297
#, scheme-format
msgid "~a and ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1228
+#: src/scm/webid-oidc/errors.scm:1300
#, scheme-format
msgid "~a, ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1232
+#: src/scm/webid-oidc/errors.scm:1304
#, 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:1307
msgid "there is an undefined variable"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1237
+#: src/scm/webid-oidc/errors.scm:1309
#, scheme-format
msgid "the origin is ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1240
+#: src/scm/webid-oidc/errors.scm:1312
#, scheme-format
msgid "a message is attached: ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1243
+#: src/scm/webid-oidc/errors.scm:1315
#, scheme-format
msgid "the values ~s are problematic"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1246
+#: src/scm/webid-oidc/errors.scm:1318
msgid "there is a kind and args"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1248
+#: src/scm/webid-oidc/errors.scm:1320
msgid "there is an assertion failure"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1250
+#: src/scm/webid-oidc/errors.scm:1322
#, scheme-format
msgid "the program quits with code ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1253
+#: src/scm/webid-oidc/errors.scm:1325
msgid "the program cannot recover from this exception"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1255
+#: src/scm/webid-oidc/errors.scm:1327
msgid "there is an error"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1257
+#: src/scm/webid-oidc/errors.scm:1329
+msgid "there is an external error"
+msgstr ""
+
+#: src/scm/webid-oidc/errors.scm:1331
#, scheme-format
msgid "Unhandled exception type ~a."
msgstr ""
diff --git a/src/Makefile.am b/src/Makefile.am
index 3dd6822..4310065 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -14,6 +14,9 @@ godir = $(libdir)/guile/$(GUILE_EFFECTIVE_VERSION)/site-ccache
webidoidcmoddir = $(moddir)/webid-oidc
webidoidcgodir = $(godir)/webid-oidc
+serverwebidoidcmoddir = $(webidoidcmoddir)/server
+serverwebidoidcgodir = $(webidoidcgodir)/server
+
dist_mod_DATA =
mod_DATA =
go_DATA =
@@ -22,8 +25,11 @@ dist_webidoidcmod_DATA =
webidoidcmod_DATA =
webidoidcgo_DATA =
-install_go_targets = install-webidoidcgoDATA
-install_mod_targets = install-webidoidcmodDATA install-dist_webidoidcmodDATA
+dist_serverwebidoidcmod_DATA =
+serverwebidoidcgo_DATA =
+
+install_go_targets = install-webidoidcgoDATA install-serverwebidoidcgoDATA
+install_mod_targets = install-webidoidcmodDATA install-dist_webidoidcmodDATA install-dist_serverwebidoidcmodDATA
include %reldir%/base64/Makefile.am
include %reldir%/random/Makefile.am
@@ -34,14 +40,15 @@ include %reldir%/pre-inst/Makefile.am
include %reldir%/inst/Makefile.am
include %reldir%/scm/Makefile.am
-CLEANFILES += $(go_DATA) $(webidoidcgo_DATA) $(mod_DATA) $(webidoidcmod_DATA)
+CLEANFILES += $(go_DATA) $(webidoidcgo_DATA) $(mod_DATA) $(webidoidcmod_DATA) \
+ $(serverwebidoidcgo_DATA)
%canon_reldir%_libwebidoidc_la_SOURCES = %reldir%/gettext.h %reldir%/libwebidoidc.c %reldir%/utilities.h
%canon_reldir%_libwebidoidc_la_LIBADD = $(noinst_LTLIBRARIES) $(GUILE_LIBS) $(NETTLE_LIBS)
INDENTED += $(%canon_reldir%_libwebidoidc_la_SOURCES)
-$(go_DATA) $(webidoidcgo_DATA): %reldir%/libwebidoidc.la
+$(go_DATA) $(webidoidcgo_DATA) $(serverwebidoidcgo_DATA): %reldir%/libwebidoidc.la
SUFFIXES += .c .x .scm .go
.c.x:
diff --git a/src/scm/webid-oidc/Makefile.am b/src/scm/webid-oidc/Makefile.am
index 6aeadfc..f248c47 100644
--- a/src/scm/webid-oidc/Makefile.am
+++ b/src/scm/webid-oidc/Makefile.am
@@ -55,3 +55,5 @@ webidoidcgo_DATA += \
%reldir%/example-app.go
EXTRA_DIST += %reldir%/ChangeLog
+
+include %reldir%/server/Makefile.am
diff --git a/src/scm/webid-oidc/errors.scm b/src/scm/webid-oidc/errors.scm
index 32423ef..bbbbc1c 100644
--- a/src/scm/webid-oidc/errors.scm
+++ b/src/scm/webid-oidc/errors.scm
@@ -870,6 +870,62 @@
(raise-exception
((record-constructor &no-provider-candidates) webid causes)))
+;; Server-side exceptions
+
+(define-exception-type
+ &resource-not-found
+ &external-error
+ make-resource-not-found
+ resource-not-found?
+ (path resource-not-found-path)
+ (cause resource-not-found-cause))
+
+(export &resource-not-found
+ make-resource-not-found
+ resource-not-found?
+ resource-not-found-path
+ resource-not-found-cause)
+
+(define-exception-type
+ &missing-etag
+ &external-error
+ make-missing-etag
+ missing-etag?
+ (data missing-etag-data))
+
+(export &missing-etag
+ make-missing-etag
+ missing-etag?
+ missing-etag-data)
+
+(define-exception-type
+ &missing-content-type
+ &external-error
+ make-missing-content-type
+ missing-content-type?
+ (data missing-content-type-data))
+
+(export &missing-content-type
+ make-missing-content-type
+ missing-content-type?
+ missing-content-type-data)
+
+(define-exception-type
+ &precondition-failed
+ &external-error
+ make-precondition-failed
+ precondition-failed?
+ (etag precondition-failed-etag)
+ (if-match precondition-failed-if-match)
+ (if-none-match precondition-failed-if-none-match))
+
+(export &precondition-failed
+ make-precondition-failed
+ precondition-failed?
+ precondition-failed-etag
+ precondition-failed-if-match
+ precondition-failed-if-none-match)
+
(define*-public (error->str err #:key (max-depth #f))
(if (record? err)
(let* ((type (record-type-descriptor err))
@@ -1193,28 +1249,44 @@
((&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_ ", "))))
+ ((&resource-not-found)
+ (format #f (G_ "the resource ~s could not be found (because ~a)")
+ (get 'path)
+ (recurse (get 'cause))))
+ ((&missing-etag)
+ (format #f (G_ "the resource is missing an etag (see ~s)")
+ (get 'data)))
+ ((&missing-content-type)
+ (format #f (G_ "the resource is missing a content type (see ~s)")
+ (get 'content-type)))
+ ((&precondition-failed)
+ (if (get 'etag)
+ (format #f (G_ "the precondition failed for etag ~s: if-match ~s and if-none-match ~s")
+ (get 'etag) (get 'if-match) (get 'if-none-match))
+ (format #f (G_ "the precondition failed for a non-existing resource: if-match ~s and if-none-match ~s")
+ (get 'if-match) (get 'if-none-match))))
((&compound-exception)
(let ((components (get 'components)))
(if (null? components)
@@ -1253,6 +1325,8 @@
(format #f (G_ "the program cannot recover from this exception")))
((&error)
(format #f (G_ "there is an error")))
+ ((&external-error)
+ (format #f (G_ "there is an external error")))
(else
(error (format #f (G_ "Unhandled exception type ~a.")
(record-type-name type))))))
diff --git a/src/scm/webid-oidc/server/Makefile.am b/src/scm/webid-oidc/server/Makefile.am
new file mode 100644
index 0000000..50708fb
--- /dev/null
+++ b/src/scm/webid-oidc/server/Makefile.am
@@ -0,0 +1,5 @@
+dist_serverwebidoidcmod_DATA += \
+ %reldir%/resource.scm
+
+serverwebidoidcgo_DATA += \
+ %reldir%/resource.go
diff --git a/src/scm/webid-oidc/server/resource.scm b/src/scm/webid-oidc/server/resource.scm
new file mode 100644
index 0000000..7a8ca0b
--- /dev/null
+++ b/src/scm/webid-oidc/server/resource.scm
@@ -0,0 +1,186 @@
+(define-module (webid-oidc server resource)
+ #:use-module (webid-oidc errors)
+ #:use-module ((webid-oidc stubs) #:prefix stubs:)
+ #:use-module (web uri)
+ #:use-module (rnrs bytevectors)
+ #:use-module (ice-9 exceptions)
+ #:use-module (ice-9 optargs)
+ #:use-module (ice-9 iconv)
+ #:use-module (ice-9 binary-ports)
+ #:use-module (oop goops)
+ #:export
+ (
+ <explicit-acl>
+ allowed-users
+ allowed-groups
+ public?
+
+ <t>
+ path
+ etag set-etag!
+ acl set-acl!
+ content-type set-content-type!
+ content set-content!
+ metadata set-matadata!
+ contained set-contained!
+
+ (my:read . read)
+ load
+ (my:write . write)
+ save
+ delete
+ ))
+
+(define-class <explicit-acl> ()
+ (allowed-users #:init-keyword #:allowed-users #:getter allowed-users)
+ (allowed-groups #:init-keyword #:allowed-groups #:getter allowed-groups)
+ (public? #:init-keyword #:public? #:getter public?))
+
+(define-class <t> ()
+ (path #:init-keyword #:path #:getter path)
+ (etag #:init-keyword #:etag #:getter etag #:setter set-etag!)
+ (acl #:init-keyword #:acl #:getter acl #:setter set-acl!)
+ (content-type #:init-keyword #:content-type #:getter content-type #:setter set-content-type!)
+ (content #:init-keyword #:content #:getter content #:setter set-content!)
+ (metadata #:init-keyword #:metadata #:getter metadata #:setter set-metadata!)
+ ;; contained is a list of paths
+ (contained #:init-keyword #:contained #:getter contained #:setter set-contained!))
+
+(define (path->file-system uri-path)
+ (let ((normalized (encode-and-join-uri-path
+ (split-and-decode-uri-path uri-path)))
+ (xdg-data-home
+ (or (getenv "XDG_DATA_HOME")
+ (format #f "~a/.local/share" (getenv "HOME")))))
+ (let ((hash (stubs:hash 'SHA-256 normalized)))
+ (let ((directory (substring hash 0 1))
+ (base (substring hash 1)))
+ (string-append xdg-data-home "/webid-oidc/server/" directory "/" base)))))
+
+(define (my:read path port)
+ (let ((data (read port)))
+ (let ((etag (assq-ref data 'etag))
+ (acl (assq-ref data 'acl))
+ (content-type (assq-ref data 'content-type))
+ (metadata (assq-ref data 'metadata))
+ (contained (assq-ref data 'contained)))
+ (unless (and etag (string? etag))
+ (raise-exception (make-missing-etag data)))
+ (unless (and content-type (symbol? content-type))
+ (raise-exception (make-missing-content-type data)))
+ (set-port-encoding! port "ISO-8859-1")
+ (let ((content (get-bytevector-all port))
+ (explicit-acl
+ (and acl
+ (if (eq? acl 'public)
+ (make <explicit-acl>
+ #:public? #t
+ #:allowed-users '()
+ #:allowed-groups '())
+ (let ((groups (assq-ref acl 'groups))
+ (users (assq-ref acl 'users)))
+ (make <explicit-acl>
+ #:public? #f
+ #:allowed-users (map string->uri users)
+ #:allowed-groups (map string->relative-ref groups))))))
+ (normalized-path
+ (let ((components (reverse (split-and-decode-uri-path path))))
+ (when (and (not (null? components))
+ (equal? (car components) ""))
+ ;; Load path with a trailing / -> it is ignored
+ (set! components (cdr components)))
+ (string-append
+ (encode-and-join-uri-path (reverse components))
+ (if contained "/" "")))))
+ (make <t>
+ #:path (string-append "/" normalized-path)
+ #:etag etag
+ #:acl explicit-acl
+ #:content-type content-type
+ #:content content
+ #:metadata (or metadata "")
+ #:contained contained)))))
+
+(define (load uri-path)
+ (with-exception-handler
+ (lambda (error)
+ (raise-exception (make-resource-not-found uri-path error)))
+ (lambda ()
+ (call-with-input-file (path->file-system uri-path)
+ (lambda (port) (my:read uri-path port))))))
+
+(define-method (my:write (obj <t>) port)
+ (let ((data `((etag . ,(etag obj))
+ (acl . ,(let ((explicit-acl (acl obj)))
+ (and explicit-acl
+ (if (public? explicit-acl)
+ 'public
+ `((users . ,(map uri->string (allowed-users explicit-acl)))
+ (groups . ,(map uri->string (allowed-groups explicit-acl))))))))
+ (content-type . ,(content-type obj))
+ (metadata . ,(metadata obj))
+ (contained . ,(contained obj)))))
+ (let ((data-stripped (filter cdr data)))
+ (write data-stripped port)
+ (set-port-encoding! port "ISO-8859-1")
+ (let ((c (content obj)))
+ (unless (string? c)
+ (set! c (bytevector->string c "ISO-8859-1")))
+ (display c port)))))
+
+(define (car-or-id x)
+ (if (pair? x) (car x) x))
+
+(define (check-precondition path if-match if-none-match)
+ (with-exception-handler
+ (lambda (not-found)
+ (unless (resource-not-found? not-found)
+ ;; This is a programming error
+ (error "This should not happen"))
+ (when if-match
+ (raise-exception (make-precondition-failed #f if-match if-none-match))))
+ (lambda ()
+ (let ((previous (load path)))
+ (let ((previous-etag (etag previous)))
+ (unless (or (not if-match)
+ (eq? if-match '*)
+ (member previous-etag (map car-or-id if-match)))
+ (raise-exception (make-precondition-failed previous-etag if-match if-none-match)))
+ (when (or (eq? if-none-match '*)
+ (and if-none-match
+ (member previous-etag (map car-or-id if-none-match))))
+ (raise-exception (make-precondition-failed previous-etag if-match if-none-match))))))
+ #:unwind? #t
+ #:unwind-for-type &resource-not-found))
+
+(define* (save obj #:key (if-match #f) (if-none-match #f))
+ (let ((fs (path->file-system (path obj))))
+ (stubs:call-with-output-file*
+ (string-append fs "~")
+ (lambda (port)
+ (flock port LOCK_EX)
+ (with-exception-handler
+ (lambda (error)
+ (flock port LOCK_UN)
+ (raise-exception error))
+ (lambda ()
+ (my:write obj port)
+ (check-precondition (path obj) if-match if-none-match)
+ (rename-file (string-append fs "~") fs)
+ (flock port LOCK_UN)))))))
+
+(define* (delete path #:key (if-match #f) (if-none-match #f))
+ (let ((fs (path->file-system path)))
+ (stubs:call-with-output-file*
+ (string-append fs "~")
+ (lambda (port)
+ (flock port LOCK_EX)
+ (with-exception-handler
+ (lambda (error)
+ (flock port LOCK_UN)
+ (raise-exception error))
+ (lambda ()
+ (check-precondition path if-match if-none-match)
+ (delete-file fs)
+ (delete-file (string-append fs "~"))
+ (flock port LOCK_UN)))))))
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 8173b9b..0031be8 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -40,7 +40,16 @@ TESTS = %reldir%/load-library.scm \
%reldir%/resource-server.scm \
%reldir%/client-authorization.scm \
%reldir%/client-token.scm \
- %reldir%/client-manifest-not-modified.scm
+ %reldir%/client-manifest-not-modified.scm \
+ %reldir%/server-read-resource.scm \
+ %reldir%/server-read-non-existing-resource.scm \
+ %reldir%/server-create-resource.scm \
+ %reldir%/server-update-resource.scm \
+ %reldir%/server-update-if-none-match.scm \
+ %reldir%/server-prevent-concurrent-update.scm \
+ %reldir%/server-prevent-concurrent-creation.scm \
+ %reldir%/server-prevent-concurrent-update-and-delete.scm \
+ %reldir%/server-prevent-concurrent-delete.scm
EXTRA_DIST += $(TESTS) %reldir%/ChangeLog
diff --git a/tests/server-create-resource.scm b/tests/server-create-resource.scm
new file mode 100644
index 0000000..c7347ad
--- /dev/null
+++ b/tests/server-create-resource.scm
@@ -0,0 +1,33 @@
+(use-modules ((webid-oidc server resource) #:prefix resource:)
+ (webid-oidc testing)
+ (webid-oidc errors)
+ (web uri)
+ (ice-9 optargs)
+ (ice-9 receive)
+ (oop goops))
+
+(define <resource:t> resource:<t>)
+(define <resource:explicit-acl> resource:<explicit-acl>)
+
+(with-test-environment
+ "server-create-resource"
+ (lambda ()
+ (with-exception-handler
+ (lambda (error)
+ #t)
+ (lambda ()
+ (resource:delete "/a/b/c"))
+ #:unwind? #t)
+ (let ((base-resource
+ (make <resource:t>
+ #:path "/a/b/c"
+ #:etag "abc"
+ #:acl (make <resource:explicit-acl>
+ #:allowed-users (list (string->uri "https://example.user/card#me"))
+ #:allowed-groups (list (string->relative-ref "/other-people#them"))
+ #:public? #f)
+ #:content-type 'application/json
+ #:content "{\"hello\": \"world\"}"
+ #:metadata "<> <> <> ."
+ #:contained #f)))
+ (resource:save base-resource #:if-none-match '*))))
diff --git a/tests/server-prevent-concurrent-creation.scm b/tests/server-prevent-concurrent-creation.scm
new file mode 100644
index 0000000..f364eff
--- /dev/null
+++ b/tests/server-prevent-concurrent-creation.scm
@@ -0,0 +1,51 @@
+(use-modules ((webid-oidc server resource) #:prefix resource:)
+ (webid-oidc testing)
+ (webid-oidc errors)
+ (web uri)
+ (ice-9 optargs)
+ (ice-9 receive)
+ (oop goops))
+
+(define <resource:t> resource:<t>)
+(define <resource:explicit-acl> resource:<explicit-acl>)
+
+(with-test-environment
+ "server-prevent-concurrent-creation"
+ (lambda ()
+ (let ((concurrent-resource
+ (make <resource:t>
+ #:path "/a/b/c"
+ #:etag "abc"
+ #:acl (make <resource:explicit-acl>
+ #:allowed-users (list (string->uri "https://example.user/card#me"))
+ #:allowed-groups (list (string->relative-ref "/other-people#them"))
+ #:public? #f)
+ #:content-type 'application/json
+ #:content "{\"hello\": \"world\"}"
+ #:metadata "<> <> <> ."
+ #:contained #f)))
+ (resource:save concurrent-resource))
+ (with-exception-handler
+ (lambda (error)
+ (unless (precondition-failed? error)
+ (exit 1))
+ (unless (equal? (precondition-failed-etag error) "abc")
+ (exit 2))
+ (unless (equal? (precondition-failed-if-none-match error) '*)
+ (exit 3))
+ (when (precondition-failed-if-match error)
+ (exit 4)))
+ (lambda ()
+ (let ((modified-resource
+ (make <resource:t>
+ #:path "/a/b/c"
+ #:etag "def"
+ #:acl #f
+ #:content-type 'text/plain
+ #:content "Hello, world"
+ #:metadata ""
+ #:contained '("/a/b/c/d"))))
+ (resource:save modified-resource #:if-none-match '*))
+ (exit 5))
+ #:unwind? #t
+ #:unwind-for-type &precondition-failed)))
diff --git a/tests/server-prevent-concurrent-delete.scm b/tests/server-prevent-concurrent-delete.scm
new file mode 100644
index 0000000..f4e2ab5
--- /dev/null
+++ b/tests/server-prevent-concurrent-delete.scm
@@ -0,0 +1,28 @@
+(use-modules ((webid-oidc server resource) #:prefix resource:)
+ (webid-oidc testing)
+ (webid-oidc errors)
+ (ice-9 optargs)
+ (ice-9 receive)
+ (oop goops))
+
+(define <resource:t> resource:<t>)
+(define <resource:explicit-acl> resource:<explicit-acl>)
+
+(with-test-environment
+ "server-prevent-concurrent-delete"
+ (lambda ()
+ (with-exception-handler
+ (lambda (error)
+ (unless (precondition-failed? error)
+ (exit 1))
+ (when (precondition-failed-etag error)
+ (exit 2))
+ (unless (equal? (precondition-failed-if-match error) '("xyz"))
+ (exit 3))
+ (when (precondition-failed-if-none-match error)
+ (exit 4)))
+ (lambda ()
+ (resource:delete "/a/b/c" #:if-match '("xyz"))
+ (exit 5))
+ #:unwind? #t
+ #:unwind-for-type &precondition-failed)))
diff --git a/tests/server-prevent-concurrent-update-and-delete.scm b/tests/server-prevent-concurrent-update-and-delete.scm
new file mode 100644
index 0000000..e28458d
--- /dev/null
+++ b/tests/server-prevent-concurrent-update-and-delete.scm
@@ -0,0 +1,42 @@
+(use-modules ((webid-oidc server resource) #:prefix resource:)
+ (webid-oidc testing)
+ (webid-oidc errors)
+ (web uri)
+ (ice-9 optargs)
+ (ice-9 receive)
+ (oop goops))
+
+(define <resource:t> resource:<t>)
+(define <resource:explicit-acl> resource:<explicit-acl>)
+
+(with-test-environment
+ "server-prevent-concurrent-update-and-delete"
+ (lambda ()
+ (let ((concurrent-resource
+ (make <resource:t>
+ #:path "/a/b/c"
+ #:etag "abc"
+ #:acl (make <resource:explicit-acl>
+ #:allowed-users (list (string->uri "https://example.user/card#me"))
+ #:allowed-groups (list (string->relative-ref "/other-people#them"))
+ #:public? #f)
+ #:content-type 'application/json
+ #:content "{\"hello\": \"world\"}"
+ #:metadata "<> <> <> ."
+ #:contained #f)))
+ (resource:save concurrent-resource))
+ (with-exception-handler
+ (lambda (error)
+ (unless (precondition-failed? error)
+ (exit 1))
+ (unless (equal? (precondition-failed-etag error) "abc")
+ (exit 2))
+ (unless (equal? (precondition-failed-if-match error) '("xyz"))
+ (exit 3))
+ (when (precondition-failed-if-none-match error)
+ (exit 4)))
+ (lambda ()
+ (resource:delete "/a/b/c" #:if-match '("xyz"))
+ (exit 5))
+ #:unwind? #t
+ #:unwind-for-type &precondition-failed)))
diff --git a/tests/server-prevent-concurrent-update.scm b/tests/server-prevent-concurrent-update.scm
new file mode 100644
index 0000000..cc20e87
--- /dev/null
+++ b/tests/server-prevent-concurrent-update.scm
@@ -0,0 +1,51 @@
+(use-modules ((webid-oidc server resource) #:prefix resource:)
+ (webid-oidc testing)
+ (webid-oidc errors)
+ (web uri)
+ (ice-9 optargs)
+ (ice-9 receive)
+ (oop goops))
+
+(define <resource:t> resource:<t>)
+(define <resource:explicit-acl> resource:<explicit-acl>)
+
+(with-test-environment
+ "server-prevent-concurrent-update"
+ (lambda ()
+ (let ((concurrent-resource
+ (make <resource:t>
+ #:path "/a/b/c"
+ #:etag "abc"
+ #:acl (make <resource:explicit-acl>
+ #:allowed-users (list (string->uri "https://example.user/card#me"))
+ #:allowed-groups (list (string->relative-ref "/other-people#them"))
+ #:public? #f)
+ #:content-type 'application/json
+ #:content "{\"hello\": \"world\"}"
+ #:metadata "<> <> <> ."
+ #:contained #f)))
+ (resource:save concurrent-resource))
+ (with-exception-handler
+ (lambda (error)
+ (unless (precondition-failed? error)
+ (exit 1))
+ (unless (equal? (precondition-failed-etag error) "abc")
+ (exit 2))
+ (unless (equal? (precondition-failed-if-match error) '("xyz"))
+ (exit 3))
+ (when (precondition-failed-if-none-match error)
+ (exit 4)))
+ (lambda ()
+ (let ((modified-resource
+ (make <resource:t>
+ #:path "/a/b/c"
+ #:etag "def"
+ #:acl #f
+ #:content-type 'text/plain
+ #:content "Hello, world"
+ #:metadata ""
+ #:contained '("/a/b/c/d"))))
+ (resource:save modified-resource #:if-match '("xyz")))
+ (exit 5))
+ #:unwind? #t
+ #:unwind-for-type &precondition-failed)))
diff --git a/tests/server-read-non-existing-resource.scm b/tests/server-read-non-existing-resource.scm
new file mode 100644
index 0000000..44ab9a8
--- /dev/null
+++ b/tests/server-read-non-existing-resource.scm
@@ -0,0 +1,19 @@
+(use-modules ((webid-oidc server resource) #:prefix resource:)
+ (webid-oidc testing)
+ (webid-oidc errors)
+ (ice-9 optargs)
+ (ice-9 receive)
+ (oop goops))
+
+(with-test-environment
+ "server-read-non-existing-resource"
+ (lambda ()
+ (with-exception-handler
+ (lambda (error)
+ (unless (resource-not-found? error)
+ (exit 1)))
+ (lambda ()
+ (let ((loaded (resource:load "/a/b/c/")))
+ (exit 2)))
+ #:unwind? #t
+ #:unwind-for-type &resource-not-found)))
diff --git a/tests/server-read-resource.scm b/tests/server-read-resource.scm
new file mode 100644
index 0000000..8a627a8
--- /dev/null
+++ b/tests/server-read-resource.scm
@@ -0,0 +1,49 @@
+(use-modules ((webid-oidc server resource) #:prefix resource:)
+ (webid-oidc testing)
+ (webid-oidc errors)
+ (web uri)
+ (ice-9 optargs)
+ (ice-9 receive)
+ (rnrs bytevectors)
+ (oop goops))
+
+(define <resource:t> resource:<t>)
+(define <resource:explicit-acl> resource:<explicit-acl>)
+
+(with-test-environment
+ "server-read-resource"
+ (lambda ()
+ (let ((base-resource
+ (make <resource:t>
+ #:path "/a/b/c"
+ #:etag "abc"
+ #:acl (make <resource:explicit-acl>
+ #:allowed-users (list (string->uri "https://example.user/card#me"))
+ #:allowed-groups (list (string->relative-ref "/other-people#them"))
+ #:public? #f)
+ #:content-type 'application/json
+ #:content "{\"hello\": \"world\"}"
+ #:metadata "<> <> <> ."
+ #:contained #f)))
+ (resource:save base-resource))
+ (let ((loaded (resource:load "/a/b/c/")))
+ (unless (equal? (resource:path loaded) "/a/b/c")
+ (exit 1))
+ (unless (equal? (resource:etag loaded) "abc")
+ (exit 2))
+ (when (resource:public? (resource:acl loaded))
+ (exit 3))
+ (unless (equal? (resource:allowed-users (resource:acl loaded))
+ (list (string->uri "https://example.user/card#me")))
+ (exit 4))
+ (unless (equal? (resource:allowed-groups (resource:acl loaded))
+ (list (string->relative-ref "/other-people#them")))
+ (exit 5))
+ (unless (eq? (resource:content-type loaded) 'application/json)
+ (exit 6))
+ (unless (equal? (resource:content loaded) (string->utf8 "{\"hello\": \"world\"}"))
+ (exit 7))
+ (unless (equal? (resource:metadata loaded) "<> <> <> .")
+ (exit 8))
+ (when (resource:contained loaded)
+ (exit 9)))))
diff --git a/tests/server-update-if-none-match.scm b/tests/server-update-if-none-match.scm
new file mode 100644
index 0000000..87e5cdd
--- /dev/null
+++ b/tests/server-update-if-none-match.scm
@@ -0,0 +1,53 @@
+(use-modules ((webid-oidc server resource) #:prefix resource:)
+ (webid-oidc testing)
+ (webid-oidc errors)
+ (web uri)
+ (ice-9 optargs)
+ (ice-9 receive)
+ (rnrs bytevectors)
+ (oop goops))
+
+(define <resource:t> resource:<t>)
+(define <resource:explicit-acl> resource:<explicit-acl>)
+
+(with-test-environment
+ "server-update-if-none-match"
+ (lambda ()
+ (let ((base-resource
+ (make <resource:t>
+ #:path "/a/b/c"
+ #:etag "abc"
+ #:acl (make <resource:explicit-acl>
+ #:allowed-users (list (string->uri "https://example.user/card#me"))
+ #:allowed-groups (list (string->relative-ref "/other-people#them"))
+ #:public? #f)
+ #:content-type 'application/json
+ #:content "{\"hello\": \"world\"}"
+ #:metadata "<> <> <> ."
+ #:contained #f)))
+ (resource:save base-resource)
+ (let ((modified-resource
+ (make <resource:t>
+ #:path "/a/b/c"
+ #:etag "def"
+ #:acl #f
+ #:content-type 'text/plain
+ #:content "Hello, world"
+ #:metadata ""
+ #:contained '("/a/b/c/d"))))
+ (resource:save modified-resource #:if-none-match '("xyz"))))
+ (let ((loaded (resource:load "/a/b/c/")))
+ (unless (equal? (resource:path loaded) "/a/b/c/")
+ (exit 1))
+ (unless (equal? (resource:etag loaded) "def")
+ (exit 2))
+ (when (resource:acl loaded)
+ (exit 3))
+ (unless (eq? (resource:content-type loaded) 'text/plain)
+ (exit 6))
+ (unless (equal? (resource:content loaded) (string->utf8 "Hello, world"))
+ (exit 7))
+ (unless (equal? (resource:metadata loaded) "")
+ (exit 8))
+ (unless (equal? (resource:contained loaded) '("/a/b/c/d"))
+ (exit 9)))))
diff --git a/tests/server-update-resource.scm b/tests/server-update-resource.scm
new file mode 100644
index 0000000..db18f3a
--- /dev/null
+++ b/tests/server-update-resource.scm
@@ -0,0 +1,53 @@
+(use-modules ((webid-oidc server resource) #:prefix resource:)
+ (webid-oidc testing)
+ (webid-oidc errors)
+ (ice-9 optargs)
+ (ice-9 receive)
+ (rnrs bytevectors)
+ (web uri)
+ (oop goops))
+
+(define <resource:t> resource:<t>)
+(define <resource:explicit-acl> resource:<explicit-acl>)
+
+(with-test-environment
+ "server-update-resource"
+ (lambda ()
+ (let ((base-resource
+ (make <resource:t>
+ #:path "/a/b/c"
+ #:etag "abc"
+ #:acl (make <resource:explicit-acl>
+ #:allowed-users (list (string->uri "https://example.user/card#me"))
+ #:allowed-groups (list (string->relative-ref "/other-people#them"))
+ #:public? #f)
+ #:content-type 'application/json
+ #:content "{\"hello\": \"world\"}"
+ #:metadata "<> <> <> ."
+ #:contained #f)))
+ (resource:save base-resource)
+ (let ((modified-resource
+ (make <resource:t>
+ #:path "/a/b/c"
+ #:etag "def"
+ #:acl #f
+ #:content-type 'text/plain
+ #:content "Hello, world"
+ #:metadata ""
+ #:contained '("/a/b/c/d"))))
+ (resource:save modified-resource #:if-match '("abc"))))
+ (let ((loaded (resource:load "/a/b/c/")))
+ (unless (equal? (resource:path loaded) "/a/b/c/") ;; container
+ (exit 1))
+ (unless (equal? (resource:etag loaded) "def")
+ (exit 2))
+ (when (resource:acl loaded)
+ (exit 3))
+ (unless (eq? (resource:content-type loaded) 'text/plain)
+ (exit 6))
+ (unless (equal? (resource:content loaded) (string->utf8 "Hello, world"))
+ (exit 7))
+ (unless (equal? (resource:metadata loaded) "")
+ (exit 8))
+ (unless (equal? (resource:contained loaded) '("/a/b/c/d"))
+ (exit 9)))))