summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVivien Kraus <vivien@planete-kraus.eu>2021-06-15 19:02:39 +0200
committerVivien Kraus <vivien@planete-kraus.eu>2021-06-17 12:24:08 +0200
commit8879c107f3b25cfd51249b75a73cea608a1bf143 (patch)
tree04ac4560c711aafe6bb3445f983dc7cde417fdfb
parent089ff9eea238de05159ed2eaee0bff93793c9a4c (diff)
Implement WAC0.4.11
-rw-r--r--doc/webid-oidc.texi21
-rw-r--r--po/fr.po272
-rw-r--r--po/webid-oidc.pot263
-rw-r--r--src/scm/webid-oidc/errors.scm20
-rw-r--r--src/scm/webid-oidc/server/resource/Makefile.am6
-rw-r--r--src/scm/webid-oidc/server/resource/wac.scm226
-rw-r--r--tests/Makefile.am3
-rw-r--r--tests/acl-with-group.scm11
-rw-r--r--tests/acl.scm249
9 files changed, 806 insertions, 265 deletions
diff --git a/doc/webid-oidc.texi b/doc/webid-oidc.texi
index 60ec866..c1fe781 100644
--- a/doc/webid-oidc.texi
+++ b/doc/webid-oidc.texi
@@ -631,6 +631,20 @@ then update the parent, then unlock the parent, and finally unlock the
child path.
@end deffn
+The Web Access Control specification defines an RDF vocabulary to
+check whether a given user is allowed to perform some operations. The
+@code{(webid-oidc server resource wac)} helps you do that.
+
+@deffn function wac-get-modes @var{server-name} @var{path} @var{user} @var{[#:http-get]}
+Return the list of modes that are allowed for @var{user} accessing
+@var{path}. The @var{server-name} URI is required to find the relevant
+triples in the ACL. If @var{user} is unauthenticated, pass @code{#f}.
+
+Please note that in any case, the data owner should have all rights
+whatsoever, bypassing WAC. Otherwise, it is possible to steal control
+away from the data owner.
+@end deffn
+
@node Running a client
@chapter Running a client
@@ -1229,6 +1243,13 @@ There was a request to delete a non-empty container.
There was a request to create a resource in something that is not a
container.
@end deftp
+
+@deftp {exception type} &cannot-fetch-group @var{group-uri} @var{cause}
+The access control could not fetch the group @var{group-uri} (with a
+known @var{cause}). This warning is continuable every time it is
+raised. If the handler returns, then the group will be considered
+empty.
+@end deftp
@node GNU Free Documentation License
@appendix GNU Free Documentation License
diff --git a/po/fr.po b/po/fr.po
index 2c499ab..7f0897b 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-06-05 16:23+0200\n"
-"PO-Revision-Date: 2021-06-05 11:07+0200\n"
+"POT-Creation-Date: 2021-06-17 12:23+0200\n"
+"PO-Revision-Date: 2021-06-17 12:24+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:931
+#: src/scm/webid-oidc/errors.scm:945
msgid "that’s how it is"
msgstr "c’est comme ça"
-#: src/scm/webid-oidc/errors.scm:936
+#: src/scm/webid-oidc/errors.scm:950
#, 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:939
+#: src/scm/webid-oidc/errors.scm:953
#, 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:942
+#: src/scm/webid-oidc/errors.scm:956
#, 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:945
+#: src/scm/webid-oidc/errors.scm:959
#, 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:950
+#: src/scm/webid-oidc/errors.scm:964
#, 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:952
+#: src/scm/webid-oidc/errors.scm:966
#, 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:957
+#: src/scm/webid-oidc/errors.scm:971
#, 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:959
+#: src/scm/webid-oidc/errors.scm:973
#, 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:964
+#: src/scm/webid-oidc/errors.scm:978
#, 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:966
+#: src/scm/webid-oidc/errors.scm:980
#, 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:971
+#: src/scm/webid-oidc/errors.scm:985
#, 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:973
+#: src/scm/webid-oidc/errors.scm:987
#, 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:976
+#: src/scm/webid-oidc/errors.scm:990
#, 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:979
+#: src/scm/webid-oidc/errors.scm:993
#, 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:982
+#: src/scm/webid-oidc/errors.scm:996
#, 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:985
+#: src/scm/webid-oidc/errors.scm:999
#, 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:988
+#: src/scm/webid-oidc/errors.scm:1002
#, 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:991
+#: src/scm/webid-oidc/errors.scm:1005
#, 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:994
+#: src/scm/webid-oidc/errors.scm:1008
#, 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:997
+#: src/scm/webid-oidc/errors.scm:1011
#, 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:1000
+#: src/scm/webid-oidc/errors.scm:1014
#, 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:1003
+#: src/scm/webid-oidc/errors.scm:1017
#, 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:1008
+#: src/scm/webid-oidc/errors.scm:1022
#, 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:1010
+#: src/scm/webid-oidc/errors.scm:1024
#, 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:1013
+#: src/scm/webid-oidc/errors.scm:1027
#, 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:1019
+#: src/scm/webid-oidc/errors.scm:1033
#, 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:1024
+#: src/scm/webid-oidc/errors.scm:1038
#, scheme-format
msgid "the webid field is incorrect: ~s"
msgstr "le champ webid est incorrect : ~s"
-#: src/scm/webid-oidc/errors.scm:1025
+#: src/scm/webid-oidc/errors.scm:1039
msgid "the webid field is missing"
msgstr "le champ webid est manquant"
-#: src/scm/webid-oidc/errors.scm:1029
+#: src/scm/webid-oidc/errors.scm:1043
#, scheme-format
msgid "the sub field is incorrect: ~s"
msgstr "le champ sub est incorrect : ~s"
-#: src/scm/webid-oidc/errors.scm:1030
+#: src/scm/webid-oidc/errors.scm:1044
msgid "the sub field is missing"
msgstr "le champ sub est manquant"
-#: src/scm/webid-oidc/errors.scm:1034
+#: src/scm/webid-oidc/errors.scm:1048
#, scheme-format
msgid "the iss field is incorrect: ~s"
msgstr "le champ iss est incorrect : ~s"
-#: src/scm/webid-oidc/errors.scm:1035
+#: src/scm/webid-oidc/errors.scm:1049
msgid "the iss field is missing"
msgstr "le champ iss est manquant"
-#: src/scm/webid-oidc/errors.scm:1039
+#: src/scm/webid-oidc/errors.scm:1053
#, scheme-format
msgid "the aud field is incorrect: ~s"
msgstr "le champ aud est incorrect : ~s"
-#: src/scm/webid-oidc/errors.scm:1040
+#: src/scm/webid-oidc/errors.scm:1054
msgid "the aud field is missing"
msgstr "le champ aud est manquant"
-#: src/scm/webid-oidc/errors.scm:1044
+#: src/scm/webid-oidc/errors.scm:1058
#, scheme-format
msgid "the iat field is incorrect: ~s"
msgstr "le champ iat est incorrect : ~s"
-#: src/scm/webid-oidc/errors.scm:1045
+#: src/scm/webid-oidc/errors.scm:1059
msgid "the iat field is missing"
msgstr "le champ iat est manquant"
-#: src/scm/webid-oidc/errors.scm:1049
+#: src/scm/webid-oidc/errors.scm:1063
#, scheme-format
msgid "the exp field is incorrect: ~s"
msgstr "le champ exp est incorrect : ~s"
-#: src/scm/webid-oidc/errors.scm:1050
+#: src/scm/webid-oidc/errors.scm:1064
msgid "the exp field is missing"
msgstr "le champ exp est manquant"
-#: src/scm/webid-oidc/errors.scm:1054
+#: src/scm/webid-oidc/errors.scm:1068
#, scheme-format
msgid "the cnf/jkt field is incorrect: ~s"
msgstr "le champ cnf/jkt est incorrect : ~s"
-#: src/scm/webid-oidc/errors.scm:1055
+#: src/scm/webid-oidc/errors.scm:1069
msgid "the cnf/jkt field is missing"
msgstr "le champ cnf/jkt est manquant"
-#: src/scm/webid-oidc/errors.scm:1059
+#: src/scm/webid-oidc/errors.scm:1073
#, scheme-format
msgid "the client-id field is incorrect: ~s"
msgstr "le champ client-id est incorrect : ~s"
-#: src/scm/webid-oidc/errors.scm:1060
+#: src/scm/webid-oidc/errors.scm:1074
msgid "the client-id field is missing"
msgstr "le champ client-id est manquant"
-#: src/scm/webid-oidc/errors.scm:1064
+#: src/scm/webid-oidc/errors.scm:1078
#: 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:1065
+#: src/scm/webid-oidc/errors.scm:1079
#: 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:1069
+#: src/scm/webid-oidc/errors.scm:1083
#, scheme-format
msgid "the typ field is incorrect: ~s"
msgstr "le champ typ est incorrect : ~s"
-#: src/scm/webid-oidc/errors.scm:1070
+#: src/scm/webid-oidc/errors.scm:1084
msgid "the typ field is missing"
msgstr "le champ typ est manquant"
-#: src/scm/webid-oidc/errors.scm:1074
+#: src/scm/webid-oidc/errors.scm:1088
#, 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:1076
+#: src/scm/webid-oidc/errors.scm:1090
msgid "the jwk field is missing"
msgstr "le champ jwk est manquant"
-#: src/scm/webid-oidc/errors.scm:1080
+#: src/scm/webid-oidc/errors.scm:1094
#, scheme-format
msgid "the jti field is incorrect: ~s"
msgstr "le champ jti est incorrect : ~s"
-#: src/scm/webid-oidc/errors.scm:1081
+#: src/scm/webid-oidc/errors.scm:1095
msgid "the jti field is missing"
msgstr "le champ jti est manquant"
-#: src/scm/webid-oidc/errors.scm:1085
+#: src/scm/webid-oidc/errors.scm:1099
#, scheme-format
msgid "the nonce field is incorrect: ~s"
msgstr "le champ nonce est incorrect : ~s"
-#: src/scm/webid-oidc/errors.scm:1086
+#: src/scm/webid-oidc/errors.scm:1100
msgid "the nonce field is missing"
msgstr "le champ nonce est manquant"
-#: src/scm/webid-oidc/errors.scm:1090
+#: src/scm/webid-oidc/errors.scm:1104
#, scheme-format
msgid "the htm field is incorrect: ~s"
msgstr "le champ htm est incorrect : ~s"
-#: src/scm/webid-oidc/errors.scm:1091
+#: src/scm/webid-oidc/errors.scm:1105
msgid "the htm field is missing"
msgstr "le champ htm est manquant"
-#: src/scm/webid-oidc/errors.scm:1095
+#: src/scm/webid-oidc/errors.scm:1109
#, scheme-format
msgid "the htu field is incorrect: ~s"
msgstr "le champ htu est incorrect : ~s"
-#: src/scm/webid-oidc/errors.scm:1096
+#: src/scm/webid-oidc/errors.scm:1110
msgid "the htu field is missing"
msgstr "le champ htu est manquant"
-#: src/scm/webid-oidc/errors.scm:1098
+#: src/scm/webid-oidc/errors.scm:1112
#, 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:1101
+#: src/scm/webid-oidc/errors.scm:1115
#, 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:1104
+#: src/scm/webid-oidc/errors.scm:1118
#, 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:1107
+#: src/scm/webid-oidc/errors.scm:1121
#, 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:1110
+#: src/scm/webid-oidc/errors.scm:1124
#, 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:1113
+#: src/scm/webid-oidc/errors.scm:1127
#, 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:1116
+#: src/scm/webid-oidc/errors.scm:1130
#, 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:1123
+#: src/scm/webid-oidc/errors.scm:1137
#, 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:1134
+#: src/scm/webid-oidc/errors.scm:1148
#, 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:1137
+#: src/scm/webid-oidc/errors.scm:1151
#, 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:1140
+#: src/scm/webid-oidc/errors.scm:1154
#, 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:1144
+#: src/scm/webid-oidc/errors.scm:1158
#, 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:1153
+#: src/scm/webid-oidc/errors.scm:1167
#, 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:1155
+#: src/scm/webid-oidc/errors.scm:1169
#, 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:1157
+#: src/scm/webid-oidc/errors.scm:1171
#, scheme-format
msgid "the key confirmation of ~s failed"
msgstr "la confirmation de la clé ~s a échoué"
-#: src/scm/webid-oidc/errors.scm:1159
+#: src/scm/webid-oidc/errors.scm:1173
#, 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:1162
+#: src/scm/webid-oidc/errors.scm:1176
#, 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:1165
+#: src/scm/webid-oidc/errors.scm:1179
#, 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:1168
+#: src/scm/webid-oidc/errors.scm:1182
#, 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:1171
+#: src/scm/webid-oidc/errors.scm:1185
#, 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:1174
+#: src/scm/webid-oidc/errors.scm:1188
#, 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:1177
+#: src/scm/webid-oidc/errors.scm:1191
#, 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:1180
+#: src/scm/webid-oidc/errors.scm:1194
#, 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:1183
+#: src/scm/webid-oidc/errors.scm:1197
msgid "I cannot serve a public manifest"
msgstr "je ne peux pas servir un manifeste public"
-#: src/scm/webid-oidc/errors.scm:1185
+#: src/scm/webid-oidc/errors.scm:1199
#, 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:1188
+#: src/scm/webid-oidc/errors.scm:1202
#, 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:1191
+#: src/scm/webid-oidc/errors.scm:1205
#, 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:1194
+#: src/scm/webid-oidc/errors.scm:1208
#, 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:1197
+#: src/scm/webid-oidc/errors.scm:1211
#, 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:1200
+#: src/scm/webid-oidc/errors.scm:1214
#, 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:1203
+#: src/scm/webid-oidc/errors.scm:1217
#, 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:1207
+#: src/scm/webid-oidc/errors.scm:1221
#, 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:1210
+#: src/scm/webid-oidc/errors.scm:1224
#, 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:1213
+#: src/scm/webid-oidc/errors.scm:1227
#, 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:1216
+#: src/scm/webid-oidc/errors.scm:1230
#, 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:1219
+#: src/scm/webid-oidc/errors.scm:1233
#, 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:1222
+#: src/scm/webid-oidc/errors.scm:1236
#, 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:1225
+#: src/scm/webid-oidc/errors.scm:1239
#, 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:1228
+#: src/scm/webid-oidc/errors.scm:1242
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:1230
+#: src/scm/webid-oidc/errors.scm:1244
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:1232
+#: src/scm/webid-oidc/errors.scm:1246
#, 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:1235
+#: src/scm/webid-oidc/errors.scm:1249
#, 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:1238
+#: src/scm/webid-oidc/errors.scm:1252
#, 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:1241
+#: src/scm/webid-oidc/errors.scm:1255
#, 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:1244
+#: src/scm/webid-oidc/errors.scm:1258
#, 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:1247
+#: src/scm/webid-oidc/errors.scm:1261
#, scheme-format
msgid ""
"~a is neither an identity provider (because ~a) nor a webid (because ~a)"
@@ -646,113 +646,122 @@ msgstr ""
"~a n’est ni un fournisseur d’identité (parce que ~a) ni un webid (parce que "
"~a)"
-#: src/scm/webid-oidc/errors.scm:1252
+#: src/scm/webid-oidc/errors.scm:1266
#, 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:1255
+#: src/scm/webid-oidc/errors.scm:1269
#, 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:1260
+#: src/scm/webid-oidc/errors.scm:1274
#, 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:1264
+#: src/scm/webid-oidc/errors.scm:1278
#, scheme-format
msgid "~s failed (because ~a)"
msgstr "~s a échoué (parce que ~a)"
-#: src/scm/webid-oidc/errors.scm:1267
+#: src/scm/webid-oidc/errors.scm:1281
msgid ", "
msgstr ", "
-#: src/scm/webid-oidc/errors.scm:1269
+#: src/scm/webid-oidc/errors.scm:1283
#, 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
+#: src/scm/webid-oidc/errors.scm:1286
#, 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
+#: src/scm/webid-oidc/errors.scm:1289
msgid "the root storage cannot be deleted"
msgstr "le stockage racine ne peut pas être détruit"
-#: src/scm/webid-oidc/errors.scm:1277
+#: src/scm/webid-oidc/errors.scm:1291
#, 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
+#: src/scm/webid-oidc/errors.scm:1294
+#, scheme-format
+msgid "the group ~s cannot be fetched (because ~a)"
+msgstr "le groupe ~s n’a pas pu être récupéré (parce que ~a)"
+
+#: src/scm/webid-oidc/errors.scm:1300
msgid "that’s it"
msgstr "c’est tout"
-#: src/scm/webid-oidc/errors.scm:1286
+#: src/scm/webid-oidc/errors.scm:1304
#, scheme-format
msgid "~a and ~a"
msgstr "~a et ~a"
-#: src/scm/webid-oidc/errors.scm:1289
+#: src/scm/webid-oidc/errors.scm:1307
#, scheme-format
msgid "~a, ~a"
msgstr "~a, ~a"
-#: src/scm/webid-oidc/errors.scm:1293
+#: src/scm/webid-oidc/errors.scm:1311
#, 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:1296
+#: src/scm/webid-oidc/errors.scm:1314
msgid "there is an undefined variable"
msgstr "il y a une variable non définie"
-#: src/scm/webid-oidc/errors.scm:1298
+#: src/scm/webid-oidc/errors.scm:1316
#, scheme-format
msgid "the origin is ~a"
msgstr "l’origine est ~a"
-#: src/scm/webid-oidc/errors.scm:1301
+#: src/scm/webid-oidc/errors.scm:1319
#, scheme-format
msgid "a message is attached: ~a"
msgstr "un message est attaché : ~a"
-#: src/scm/webid-oidc/errors.scm:1304
+#: src/scm/webid-oidc/errors.scm:1322
#, scheme-format
msgid "the values ~s are problematic"
msgstr "les valeurs ~s sont problématiques"
-#: src/scm/webid-oidc/errors.scm:1307
+#: src/scm/webid-oidc/errors.scm:1325
msgid "there is a kind and args"
msgstr "il y a un type et des arguments"
-#: src/scm/webid-oidc/errors.scm:1309
+#: src/scm/webid-oidc/errors.scm:1327
msgid "there is an assertion failure"
msgstr "il y a un échec d’assertion"
-#: src/scm/webid-oidc/errors.scm:1311
+#: src/scm/webid-oidc/errors.scm:1329
#, scheme-format
msgid "the program quits with code ~a"
msgstr "le programme quitte avec le code ~a"
-#: src/scm/webid-oidc/errors.scm:1314
+#: src/scm/webid-oidc/errors.scm:1332
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:1316
+#: src/scm/webid-oidc/errors.scm:1334
+msgid "there is an external error"
+msgstr "il y a une erreur externe"
+
+#: src/scm/webid-oidc/errors.scm:1336
msgid "there is an error"
msgstr "il y a une erreur"
-#: src/scm/webid-oidc/errors.scm:1318
+#: src/scm/webid-oidc/errors.scm:1338
#, scheme-format
msgid "Unhandled exception type ~a."
msgstr "Type d’exception non pris en charge ~a."
@@ -1633,13 +1642,6 @@ msgstr "Il y a eu une erreur : ~a\n"
#~ msgstr "le groupe ~a n’est pas sous l’URI du serveur ~a"
#, scheme-format
-#~ msgid "the group ~a cannot be fetched (because ~a)"
-#~ msgstr "le groupe ~a n’a pas pu être récupéré (parce que ~a)"
-
-#~ msgid "there is an external error"
-#~ msgstr "il y a une erreur externe"
-
-#, scheme-format
#~ msgid ""
#~ "The application is not a Solid application because the client ID, "
#~ "<strong>~a</strong>, is not a valid URI."
diff --git a/po/webid-oidc.pot b/po/webid-oidc.pot
index 7653461..1f9fd31 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:23+0200\n"
+"POT-Creation-Date: 2021-06-17 12:23+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -122,614 +122,623 @@ msgstr ""
msgid "Usage: generate-key [NUMBER OF BITS | CURVE]\n"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:931
+#: src/scm/webid-oidc/errors.scm:945
msgid "that’s how it is"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:936
+#: src/scm/webid-oidc/errors.scm:950
#, scheme-format
msgid "the value ~s is not a base64 string (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:939
+#: src/scm/webid-oidc/errors.scm:953
#, scheme-format
msgid "the value ~s is not JSON (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:942
+#: src/scm/webid-oidc/errors.scm:956
#, scheme-format
msgid "the value ~s is not Turtle (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:945
+#: src/scm/webid-oidc/errors.scm:959
#, scheme-format
msgid "the value ~s does not identify an elleptic curve"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:950
+#: src/scm/webid-oidc/errors.scm:964
#, scheme-format
msgid "the value ~s does not identify a JWK (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:952
+#: src/scm/webid-oidc/errors.scm:966
#, scheme-format
msgid "the value ~s does not identify a JWK"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:957
+#: src/scm/webid-oidc/errors.scm:971
#, scheme-format
msgid "the value ~s does not identify a public JWK (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:959
+#: src/scm/webid-oidc/errors.scm:973
#, scheme-format
msgid "the value ~s does not identify a public JWK"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:964
+#: src/scm/webid-oidc/errors.scm:978
#, scheme-format
msgid "the value ~s does not identify a private JWK (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:966
+#: src/scm/webid-oidc/errors.scm:980
#, scheme-format
msgid "the value ~s does not identify a private JWK"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:971
+#: src/scm/webid-oidc/errors.scm:985
#, scheme-format
msgid "the value ~s does not identify a JWKS (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:973
+#: src/scm/webid-oidc/errors.scm:987
#, scheme-format
msgid "the value ~s does not identify a JWKS"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:976
+#: src/scm/webid-oidc/errors.scm:990
#, scheme-format
msgid "the value ~s does not identify a hash algorithm"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:979
+#: src/scm/webid-oidc/errors.scm:993
#, scheme-format
msgid "the value ~s is not an alist or misses key ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:982
+#: src/scm/webid-oidc/errors.scm:996
#, scheme-format
msgid "the value ~s is not a JWS header (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:985
+#: src/scm/webid-oidc/errors.scm:999
#, scheme-format
msgid "the value ~s is not a JWS payload (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:988
+#: src/scm/webid-oidc/errors.scm:1002
#, scheme-format
msgid "the value ~s is not a JWS (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:991
+#: src/scm/webid-oidc/errors.scm:1005
#, scheme-format
msgid "the string ~s cannot be split in 3 parts with ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:994
+#: src/scm/webid-oidc/errors.scm:1008
#, 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:997
+#: src/scm/webid-oidc/errors.scm:1011
#, scheme-format
msgid "I cannot decode JWS ~a (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1000
+#: src/scm/webid-oidc/errors.scm:1014
#, scheme-format
msgid "I cannot encode JWS ~a (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1003
+#: src/scm/webid-oidc/errors.scm:1017
#, scheme-format
msgid ""
"the server request unexpectedly failed with code ~a and reason phrase ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1008
+#: src/scm/webid-oidc/errors.scm:1022
#, scheme-format
msgid "the header ~a should not have the value ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1010
+#: src/scm/webid-oidc/errors.scm:1024
#, scheme-format
msgid "the header ~a should be present"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1013
+#: src/scm/webid-oidc/errors.scm:1027
#, scheme-format
msgid "the server response wasn't expected: ~s (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1019
+#: src/scm/webid-oidc/errors.scm:1033
#, scheme-format
msgid "the value ~s is not an OIDC configuration (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1024
+#: src/scm/webid-oidc/errors.scm:1038
#, scheme-format
msgid "the webid field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1025
+#: src/scm/webid-oidc/errors.scm:1039
msgid "the webid field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1029
+#: src/scm/webid-oidc/errors.scm:1043
#, scheme-format
msgid "the sub field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1030
+#: src/scm/webid-oidc/errors.scm:1044
msgid "the sub field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1034
+#: src/scm/webid-oidc/errors.scm:1048
#, scheme-format
msgid "the iss field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1035
+#: src/scm/webid-oidc/errors.scm:1049
msgid "the iss field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1039
+#: src/scm/webid-oidc/errors.scm:1053
#, scheme-format
msgid "the aud field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1040
+#: src/scm/webid-oidc/errors.scm:1054
msgid "the aud field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1044
+#: src/scm/webid-oidc/errors.scm:1058
#, scheme-format
msgid "the iat field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1045
+#: src/scm/webid-oidc/errors.scm:1059
msgid "the iat field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1049
+#: src/scm/webid-oidc/errors.scm:1063
#, scheme-format
msgid "the exp field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1050
+#: src/scm/webid-oidc/errors.scm:1064
msgid "the exp field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1054
+#: src/scm/webid-oidc/errors.scm:1068
#, scheme-format
msgid "the cnf/jkt field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1055
+#: src/scm/webid-oidc/errors.scm:1069
msgid "the cnf/jkt field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1059
+#: src/scm/webid-oidc/errors.scm:1073
#, scheme-format
msgid "the client-id field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1060
+#: src/scm/webid-oidc/errors.scm:1074
msgid "the client-id field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1064
+#: src/scm/webid-oidc/errors.scm:1078
#: 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:1065
+#: src/scm/webid-oidc/errors.scm:1079
#: src/scm/webid-oidc/authorization-page-unsafe.scm:134
msgid "the redirect_uris field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1069
+#: src/scm/webid-oidc/errors.scm:1083
#, scheme-format
msgid "the typ field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1070
+#: src/scm/webid-oidc/errors.scm:1084
msgid "the typ field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1074
+#: src/scm/webid-oidc/errors.scm:1088
#, scheme-format
msgid "the jwk field is incorrect: ~s (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1076
+#: src/scm/webid-oidc/errors.scm:1090
msgid "the jwk field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1080
+#: src/scm/webid-oidc/errors.scm:1094
#, scheme-format
msgid "the jti field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1081
+#: src/scm/webid-oidc/errors.scm:1095
msgid "the jti field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1085
+#: src/scm/webid-oidc/errors.scm:1099
#, scheme-format
msgid "the nonce field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1086
+#: src/scm/webid-oidc/errors.scm:1100
msgid "the nonce field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1090
+#: src/scm/webid-oidc/errors.scm:1104
#, scheme-format
msgid "the htm field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1091
+#: src/scm/webid-oidc/errors.scm:1105
msgid "the htm field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1095
+#: src/scm/webid-oidc/errors.scm:1109
#, scheme-format
msgid "the htu field is incorrect: ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1096
+#: src/scm/webid-oidc/errors.scm:1110
msgid "the htu field is missing"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1098
+#: src/scm/webid-oidc/errors.scm:1112
#, scheme-format
msgid "~s is not an access token (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1101
+#: src/scm/webid-oidc/errors.scm:1115
#, scheme-format
msgid "~s is not an access token header (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1104
+#: src/scm/webid-oidc/errors.scm:1118
#, scheme-format
msgid "~s is not an access token payload (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1107
+#: src/scm/webid-oidc/errors.scm:1121
#, scheme-format
msgid "~s is not a DPoP proof (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1110
+#: src/scm/webid-oidc/errors.scm:1124
#, scheme-format
msgid "~s is not a DPoP proof header (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1113
+#: src/scm/webid-oidc/errors.scm:1127
#, scheme-format
msgid "~s is not a DPoP proof payload (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1116
+#: src/scm/webid-oidc/errors.scm:1130
#, scheme-format
msgid "I cannot fetch the issuer configuration of ~a (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1123
+#: src/scm/webid-oidc/errors.scm:1137
#, scheme-format
msgid "I cannot fetch the JWKS of ~a at ~a (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1134
+#: src/scm/webid-oidc/errors.scm:1148
#, scheme-format
msgid "the HTTP method is signed for ~s, but ~s was requested"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1137
+#: src/scm/webid-oidc/errors.scm:1151
#, scheme-format
msgid "the HTTP uri is signed for ~a, but ~a was requested"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1140
+#: src/scm/webid-oidc/errors.scm:1154
#, 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:1144
+#: src/scm/webid-oidc/errors.scm:1158
#, 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:1153
+#: src/scm/webid-oidc/errors.scm:1167
#, scheme-format
msgid "the key ~s does not hash to ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1155
+#: src/scm/webid-oidc/errors.scm:1169
#, scheme-format
msgid "the key confirmation of ~s failed (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1157
+#: src/scm/webid-oidc/errors.scm:1171
#, scheme-format
msgid "the key confirmation of ~s failed"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1159
+#: src/scm/webid-oidc/errors.scm:1173
#, scheme-format
msgid "the jti ~s has already been found (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1162
+#: src/scm/webid-oidc/errors.scm:1176
#, scheme-format
msgid "I cannot decode ~s as an access token (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1165
+#: src/scm/webid-oidc/errors.scm:1179
#, scheme-format
msgid "I cannot encode ~s as an access token with key ~s (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1168
+#: src/scm/webid-oidc/errors.scm:1182
#, scheme-format
msgid "I cannot decode ~s as a DPoP proof (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1171
+#: src/scm/webid-oidc/errors.scm:1185
#, scheme-format
msgid "I cannot encode ~s as a DPoP proof (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1174
+#: src/scm/webid-oidc/errors.scm:1188
#, scheme-format
msgid "I could not fetch a RDF graph at ~a (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1177
+#: src/scm/webid-oidc/errors.scm:1191
#, scheme-format
msgid "~s is not a client manifest (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1180
+#: src/scm/webid-oidc/errors.scm:1194
#, scheme-format
msgid "~s does not authorize redirection URI ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1183
+#: src/scm/webid-oidc/errors.scm:1197
msgid "I cannot serve a public manifest"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1185
+#: src/scm/webid-oidc/errors.scm:1199
#, scheme-format
msgid "~a does not have a client manifest registration triple"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1188
+#: src/scm/webid-oidc/errors.scm:1202
#, scheme-format
msgid "the client manifest at ~a is advertised for ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1191
+#: src/scm/webid-oidc/errors.scm:1205
#, scheme-format
msgid "I could not fetch the client manifest of ~a (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1194
+#: src/scm/webid-oidc/errors.scm:1208
#, scheme-format
msgid "~s is not an authorization code (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1197
+#: src/scm/webid-oidc/errors.scm:1211
#, scheme-format
msgid "~s is not an authorization code header (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1200
+#: src/scm/webid-oidc/errors.scm:1214
#, scheme-format
msgid "~s is not an authorization code payload (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1203
+#: src/scm/webid-oidc/errors.scm:1217
#, scheme-format
msgid "the current time is ~a, and the authorization code expired at ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1207
+#: src/scm/webid-oidc/errors.scm:1221
#, scheme-format
msgid "I cannot decode ~s as an authorization code (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1210
+#: src/scm/webid-oidc/errors.scm:1224
#, scheme-format
msgid "I cannot encode ~s as an authorization code (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1213
+#: src/scm/webid-oidc/errors.scm:1227
#, scheme-format
msgid "there is no such refresh token as ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1216
+#: src/scm/webid-oidc/errors.scm:1230
#, 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:1219
+#: src/scm/webid-oidc/errors.scm:1233
#, scheme-format
msgid "I cannot decode ~s as an ID token (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1222
+#: src/scm/webid-oidc/errors.scm:1236
#, scheme-format
msgid "I cannot encode ~s as an ID token (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1225
+#: src/scm/webid-oidc/errors.scm:1239
#, scheme-format
msgid "the grant type ~s is not supported"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1228
+#: src/scm/webid-oidc/errors.scm:1242
msgid "there is no authorization code in the request"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1230
+#: src/scm/webid-oidc/errors.scm:1244
msgid "there is no refresh token in the request"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1232
+#: src/scm/webid-oidc/errors.scm:1246
#, scheme-format
msgid "~s is not an ID token (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1235
+#: src/scm/webid-oidc/errors.scm:1249
#, scheme-format
msgid "~s is not an ID token header (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1238
+#: src/scm/webid-oidc/errors.scm:1252
#, scheme-format
msgid "~s is not an ID token payload (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1241
+#: src/scm/webid-oidc/errors.scm:1255
#, 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:1244
+#: src/scm/webid-oidc/errors.scm:1258
#, scheme-format
msgid "~s does not admit ~s as an identity provider"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1247
+#: src/scm/webid-oidc/errors.scm:1261
#, scheme-format
msgid ""
"~a is neither an identity provider (because ~a) nor a webid (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1252
+#: src/scm/webid-oidc/errors.scm:1266
#, scheme-format
msgid "the token request failed (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1255
+#: src/scm/webid-oidc/errors.scm:1269
#, 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:1260
+#: src/scm/webid-oidc/errors.scm:1274
#, scheme-format
msgid "all identity provider candidates for ~a failed: ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1264
+#: src/scm/webid-oidc/errors.scm:1278
#, scheme-format
msgid "~s failed (because ~a)"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1267
+#: src/scm/webid-oidc/errors.scm:1281
msgid ", "
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1269
+#: src/scm/webid-oidc/errors.scm:1283
#, scheme-format
msgid "no resource has been found to serve URI path ~s"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1272
+#: src/scm/webid-oidc/errors.scm:1286
#, scheme-format
msgid "no resource has been found to serve URI path ~s, but ~s exists"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1275
+#: src/scm/webid-oidc/errors.scm:1289
msgid "the root storage cannot be deleted"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1277
+#: src/scm/webid-oidc/errors.scm:1291
#, scheme-format
msgid "the container ~s should be emptied before being deleted"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1282
+#: src/scm/webid-oidc/errors.scm:1294
+#, scheme-format
+msgid "the group ~s cannot be fetched (because ~a)"
+msgstr ""
+
+#: src/scm/webid-oidc/errors.scm:1300
msgid "that’s it"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1286
+#: src/scm/webid-oidc/errors.scm:1304
#, scheme-format
msgid "~a and ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1289
+#: src/scm/webid-oidc/errors.scm:1307
#, scheme-format
msgid "~a, ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1293
+#: src/scm/webid-oidc/errors.scm:1311
#, scheme-format
msgid "the signature ~a does not match key ~s with payload ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1296
+#: src/scm/webid-oidc/errors.scm:1314
msgid "there is an undefined variable"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1298
+#: src/scm/webid-oidc/errors.scm:1316
#, scheme-format
msgid "the origin is ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1301
+#: src/scm/webid-oidc/errors.scm:1319
#, scheme-format
msgid "a message is attached: ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1304
+#: src/scm/webid-oidc/errors.scm:1322
#, scheme-format
msgid "the values ~s are problematic"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1307
+#: src/scm/webid-oidc/errors.scm:1325
msgid "there is a kind and args"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1309
+#: src/scm/webid-oidc/errors.scm:1327
msgid "there is an assertion failure"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1311
+#: src/scm/webid-oidc/errors.scm:1329
#, scheme-format
msgid "the program quits with code ~a"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1314
+#: src/scm/webid-oidc/errors.scm:1332
msgid "the program cannot recover from this exception"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1316
+#: src/scm/webid-oidc/errors.scm:1334
+msgid "there is an external error"
+msgstr ""
+
+#: src/scm/webid-oidc/errors.scm:1336
msgid "there is an error"
msgstr ""
-#: src/scm/webid-oidc/errors.scm:1318
+#: src/scm/webid-oidc/errors.scm:1338
#, 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 60e45f7..c6802d7 100644
--- a/src/scm/webid-oidc/errors.scm
+++ b/src/scm/webid-oidc/errors.scm
@@ -920,6 +920,20 @@
container-not-empty?
container-not-empty-path)
+(define-exception-type
+ &cannot-fetch-group
+ &warning
+ make-cannot-fetch-group
+ cannot-fetch-group?
+ (group-uri cannot-fetch-group-group-uri)
+ (cause cannot-fetch-group-cause))
+
+(export &cannot-fetch-group
+ make-cannot-fetch-group
+ cannot-fetch-group?
+ cannot-fetch-group-group-uri
+ cannot-fetch-group-cause)
+
(define*-public (error->str err #:key (max-depth #f))
(if (record? err)
(let* ((type (record-type-descriptor err))
@@ -1276,6 +1290,10 @@
((&container-not-empty)
(format #f (G_ "the container ~s should be emptied before being deleted")
(get 'path)))
+ ((&cannot-fetch-group)
+ (format #f (G_ "the group ~s cannot be fetched (because ~a)"
+ (uri->string (get 'group-uri))
+ (recurse (get 'cause)))))
((&compound-exception)
(let ((components (get 'components)))
(if (null? components)
@@ -1312,6 +1330,8 @@
(get 'code)))
((&non-continuable)
(format #f (G_ "the program cannot recover from this exception")))
+ ((&external-error)
+ (format #f (G_ "there is an external error")))
((&error)
(format #f (G_ "there is an error")))
(else
diff --git a/src/scm/webid-oidc/server/resource/Makefile.am b/src/scm/webid-oidc/server/resource/Makefile.am
index 49cc912..efc41ce 100644
--- a/src/scm/webid-oidc/server/resource/Makefile.am
+++ b/src/scm/webid-oidc/server/resource/Makefile.am
@@ -1,7 +1,9 @@
dist_resourceserverwebidoidcmod_DATA += \
%reldir%/content.scm \
- %reldir%/path.scm
+ %reldir%/path.scm \
+ %reldir%/wac.scm
resourceserverwebidoidcgo_DATA += \
%reldir%/content.go \
- %reldir%/path.go
+ %reldir%/path.go \
+ %reldir%/wac.go
diff --git a/src/scm/webid-oidc/server/resource/wac.scm b/src/scm/webid-oidc/server/resource/wac.scm
new file mode 100644
index 0000000..e482ce4
--- /dev/null
+++ b/src/scm/webid-oidc/server/resource/wac.scm
@@ -0,0 +1,226 @@
+(define-module (webid-oidc server resource wac)
+ #:use-module (webid-oidc errors)
+ #:use-module (webid-oidc server resource path)
+ #:use-module (webid-oidc server resource content)
+ #:use-module (webid-oidc cache)
+ #:use-module (webid-oidc fetch)
+ #: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 (web client)
+ #:use-module (rdf rdf)
+ #:use-module (turtle tordf)
+ #: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
+ (
+
+ wac-get-modes
+
+ ))
+
+(define (group-member? http-get group-uri agent)
+ (when (string? group-uri)
+ (set! group-uri (string->uri group-uri)))
+ (when (string? agent)
+ (set! group-uri (string->uri agent)))
+ (let ((group-doc-uri
+ (build-uri (uri-scheme group-uri)
+ #:userinfo (uri-userinfo group-uri)
+ #:host (uri-host group-uri)
+ #:port (uri-port group-uri)
+ #:path (uri-path group-uri)
+ #:query (uri-query group-uri))))
+ (with-exception-handler
+ (lambda (error)
+ (raise-exception
+ (make-cannot-fetch-group group-uri error)
+ #:continuable? #t)
+ #f)
+ (lambda ()
+ (let ((data (fetch group-doc-uri #:http-get http-get)))
+ (with-index
+ data
+ (lambda (rdf-match)
+ (not (null?
+ (rdf-match (uri->string group-uri)
+ "http://www.w3.org/2006/vcard/ns#hasMember"
+ (uri->string agent))))))))
+ #:unwind? #t
+ #:unwind-for-type &cannot-fetch-linked-data)))
+
+(define (with-rdf-source server-name path content-type static-content f)
+ (with-index
+ (case content-type
+ ((text/turtle)
+ (turtle->rdf (string-append
+ "# This is not a file name\n"
+ (utf8->string static-content))
+ (uri->string
+ (build-uri (uri-scheme server-name)
+ #:userinfo (uri-userinfo server-name)
+ #:host (uri-host server-name)
+ #:port (uri-port server-name)
+ #:path (string-append path ".acl"))))))
+ f))
+
+(define (check-authorization path check-default? server-name final-path http-get user rdf-match id)
+ ;; The authorization should give accessTo path,
+ ;; or to a prefix of final-path; and it should
+ ;; be for agent user, or a group that contains
+ ;; user.
+ (let ((access-to-ok
+ (and
+ ;; We’re looking for acl:accessTo targetting path
+ (not
+ (null?
+ (rdf-match id "http://www.w3.org/ns/auth/acl#accessTo"
+ (uri->string
+ (build-uri (uri-scheme server-name)
+ #:userinfo (uri-userinfo server-name)
+ #:host (uri-host server-name)
+ #:port (uri-port server-name)
+ #:path path)))))
+ (or (not check-default?)
+ ;; We’re also looking for acl:default statement
+ ;; targetting a prefix of final-path
+ (let ((defaults
+ (map rdf-triple-object
+ (rdf-match id "http://www.w3.org/ns/auth/acl#default" #f))))
+ (define (default-ok? uri)
+ (and (string? uri)
+ (string->uri uri)
+ (let ((uri (string->uri uri)))
+ (and (eq? (uri-scheme uri)
+ (uri-scheme server-name))
+ (equal? (uri-userinfo uri)
+ (uri-userinfo server-name))
+ (equal? (uri-host uri)
+ (uri-host server-name))
+ (equal? (uri-port uri)
+ (uri-port server-name))
+ (let ((final-path-components
+ (split-and-decode-uri-path final-path))
+ (default-components
+ (split-and-decode-uri-path (uri-path uri))))
+ (define (prefix? x y)
+ (or (null? x)
+ (and (not (null? y))
+ (equal? (car x) (car y))
+ (prefix? (cdr x) (cdr y)))))
+ (prefix? default-components final-path-components))))))
+ (not (null? (filter default-ok? defaults)))))))
+ (agent-ok
+ (let ((groups
+ (map rdf-triple-object
+ (rdf-match id
+ "http://www.w3.org/ns/auth/acl#agentGroup"
+ #f)))
+ (specific-agent-ok?
+ (and user
+ (not (null?
+ (rdf-match id
+ "http://www.w3.org/ns/auth/acl#agent"
+ (uri->string user))))))
+ (public-access?
+ (not (null?
+ (rdf-match id
+ "http://www.w3.org/ns/auth/acl#agentClass"
+ "http://xmlns.com/foaf/0.1/Agent"))))
+ (authenticated-access?
+ (not (null?
+ (rdf-match id
+ "http://www.w3.org/ns/auth/acl#agentClass"
+ "http://www.w3.org/ns/auth/acl#AuthenticatedAgent")))))
+ (or public-access?
+ (and user authenticated-access?)
+ specific-agent-ok?
+ (and user
+ (not (null?
+ (filter (lambda (group)
+ (group-member? http-get group user))
+ groups))))))))
+ (or
+ (and access-to-ok
+ agent-ok
+ (filter
+ (lambda (x) x)
+ (map (lambda (triple)
+ (let ((mode (rdf-triple-object triple)))
+ (and (string? mode)
+ (string->uri mode))))
+ (rdf-match id
+ "http://www.w3.org/ns/auth/acl#mode"
+ #f))))
+ '())))
+
+(define (check-authorizations path check-default? server-name final-path http-get user rdf-match
+ allowed-modes authorizations)
+ (if (null? authorizations)
+ (reverse allowed-modes)
+ (let ((new-modes
+ (check-authorization path check-default? server-name final-path http-get user rdf-match
+ (car authorizations))))
+ (check-authorizations
+ path check-default? server-name final-path http-get user rdf-match
+ (append (reverse new-modes) allowed-modes)
+ (cdr authorizations)))))
+
+(define acl-aux (string->uri "http://www.w3.org/ns/auth/acl#accessControl"))
+
+(define* (wac-get-modes server-name final-path user
+ #:key
+ (http-get http-get))
+ (with-session
+ (lambda (content-type contained static-content create delete)
+ (define (wac-check-recursive path check-default?)
+ (receive (main-etag auxiliary) (read-path path)
+ (let ((acl-etag (assoc-ref auxiliary acl-aux)))
+ (if acl-etag
+ (with-rdf-source
+ server-name path (content-type acl-etag) (static-content acl-etag)
+ (lambda (rdf-match)
+ (check-authorizations
+ path check-default? server-name final-path http-get user rdf-match
+ '()
+ (map rdf-triple-subject
+ (rdf-match #f
+ "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"
+ "http://www.w3.org/ns/auth/acl#Authorization")))))
+ ;; No existing ACL.
+ (let ((parent-path
+ (string-append
+ "/"
+ (encode-and-join-uri-path
+ (reverse
+ (cdr
+ (reverse
+ (split-and-decode-uri-path path)))))
+ "/")))
+ (when (equal? parent-path "//")
+ ;; The parent is the root
+ (set! parent-path "/"))
+ (wac-check-recursive parent-path #t))))))
+ (let ((all-modes (wac-check-recursive final-path #f)))
+ (define (accumulate-unique accumulated list)
+ (cond
+ ((null? list)
+ (reverse accumulated))
+ ((or (null? accumulated) (not (equal? (car accumulated) (car list))))
+ (accumulate-unique (cons (car list) accumulated) (cdr list)))
+ (else
+ (accumulate-unique accumulated (cdr list)))))
+ (accumulate-unique
+ '()
+ (sort all-modes
+ (lambda (a b)
+ (string< (uri->string a) (uri->string b)))))))))
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 4d7fda4..34f0964 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -43,7 +43,8 @@ TESTS = %reldir%/load-library.scm \
%reldir%/client-manifest-not-modified.scm \
%reldir%/server-content.scm \
%reldir%/server-path.scm \
- %reldir%/http-link.scm
+ %reldir%/http-link.scm \
+ %reldir%/acl.scm
EXTRA_DIST += $(TESTS) %reldir%/ChangeLog
diff --git a/tests/acl-with-group.scm b/tests/acl-with-group.scm
new file mode 100644
index 0000000..210cc21
--- /dev/null
+++ b/tests/acl-with-group.scm
@@ -0,0 +1,11 @@
+(define (http-get uri)
+ (unless (equal? uri
+ (string->uri "https://group-server.example.com/the#group"))
+ (exit 1)
+ (values
+ (build-response #:headers '((content-type text/turtle)))
+ "@prefix vcard: <http://www.w3.org/2006/vcard/ns#>.
+
+<#group> a vcard:Group;
+ vcard:hasMember <https://other-user.example.com/profile/card#me> .
+")))
diff --git a/tests/acl.scm b/tests/acl.scm
new file mode 100644
index 0000000..b582b17
--- /dev/null
+++ b/tests/acl.scm
@@ -0,0 +1,249 @@
+(use-modules (webid-oidc server resource wac)
+ (webid-oidc server resource content)
+ (webid-oidc server resource path)
+ (webid-oidc testing)
+ (web http)
+ (web request)
+ (web response)
+ (web uri))
+
+(define (http-get uri . other-args)
+ (when (string? uri)
+ (set! uri (string->uri uri)))
+ (unless (equal? uri
+ (string->uri "https://fbi.databox.me/group"))
+ (format (current-error-port)
+ "Expected:\n ~s, got:\n ~s\n" uri (string->uri "https://fbi.databox.me/group"))
+ (exit 1))
+ (values
+ (build-response #:headers '((content-type text/turtle)))
+ "@prefix vcard: <http://www.w3.org/2006/vcard/ns#>.
+
+<#spies> a vcard:Group;
+ vcard:hasMember <https://the-spy.databox.me/profile/card#me> .
+"))
+
+(with-test-environment
+ "direct-acl"
+ (lambda ()
+ (for-each
+ (lambda (f)
+ (false-if-exception
+ (delete-file
+ (string-append
+ "tests/direct-acl.home/webid-oidc/server/content/"
+ f))))
+ '("6/8OMG_V5x-KmI6TI"
+ "X/hqM_2Avn5_egTzs"
+ "a/68pTwiImTWTpjQl"
+ "5/n1KPgAd3ng4wSqn"
+ "D/wxU0ogx5rzRrvu2"
+ "F/BQKBGrtq6U_M0L7"
+ "n/U46BXbknEaLWZpH"
+ "N/gnO8RAS9FpPiO5j"
+ "A/fkGTJRCHc-jHk-V"
+ "H/y4S5p1BqTEJi-Jb"
+ "b/k7RqZevpCHAumba"
+ "y/29x0MEOMybxUqDU"
+ "5/KVojpXDg0Aob3_v"))
+ (with-session
+ (lambda (content-type contained static-content create delete)
+ ;; In this little scenario:
+ ;; / can only be listed by Alice and the FBI
+ ;; /docs/ can only be updated by Alice and the public can list
+ ;; /docs/file1 can only be updated by Alice, but public
+ ;; /docs/file2 same, but authenticated
+ ;; /private-docs/ private to Alice, no ACL
+ ;; /private-docs/file1 no ACL (so, readable by the FBI as inherited in /)
+ ;; /private/docs/file2 no ACL (so, not readable by the FBI)
+ (let ((/ (create 'text/turtle '("docs" "private-docs") ""))
+ (/docs/ (create 'text/turtle '("file1" "file2") ""))
+ (/docs/file1 (create 'text/plain #f "Hello :)"))
+ (/docs/file2 (create 'text/plain #f "You’re authenticated :)"))
+ (/private-docs/ (create 'text/turtle '("file1") ""))
+ (/private-docs/file1 (create 'text/plain #f "Private, but FBI can read!"))
+ (/private-docs/file2 (create 'text/plain #f "Private!"))
+ (/.acl (create 'text/turtle #f "@prefix acl: <http://www.w3.org/ns/auth/acl#> .
+
+<#default>
+ a acl:Authorization;
+ acl:accessTo <https://alice.databox.me/>;
+ acl:agent <https://alice.databox.me/profile/card#me>;
+ acl:mode acl:Read, acl:Write, acl:Control;
+ acl:default <https://alice.databox.me/>.
+
+<#for-the-fbi>
+ a acl:Authorization;
+ acl:accessTo <https://alice.databox.me/>;
+ acl:agentGroup <https://fbi.databox.me/group#spies>;
+ acl:mode acl:Read, acl:Write;
+ acl:default <https://alice.databox.me/private-docs/file1>.
+"))
+ (/docs/.acl (create 'text/turtle #f "@prefix acl: <http://www.w3.org/ns/auth/acl#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/>.
+
+<#default>
+ a acl:Authorization;
+ acl:accessTo <https://alice.databox.me/docs/>;
+ acl:agent <https://alice.databox.me/profile/card#me>;
+ acl:mode acl:Read, acl:Write, acl:Control.
+
+<#anyone-can-list-files>
+ a acl:Authorization;
+ acl:accessTo <https://alice.databox.me/docs/>;
+ acl:agentClass foaf:Agent;
+ acl:mode acl:Read.
+"))
+ (/docs/file1.acl (create 'text/turtle #f "@prefix acl: <http://www.w3.org/ns/auth/acl#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/>.
+
+<#default>
+ a acl:Authorization;
+ acl:accessTo <https://alice.databox.me/docs/file1>;
+ acl:agent <https://alice.databox.me/profile/card#me>;
+ acl:mode acl:Read, acl:Write, acl:Control.
+
+<#public>
+ a acl:Authorization;
+ acl:accessTo <https://alice.databox.me/docs/file1>;
+ acl:agentClass foaf:Agent;
+ acl:mode acl:Read.
+"))
+ (/docs/file2.acl (create 'text/turtle #f "@prefix acl: <http://www.w3.org/ns/auth/acl#> .
+
+<#default>
+ a acl:Authorization;
+ acl:accessTo <https://alice.databox.me/docs/file2>;
+ acl:agent <https://alice.databox.me/profile/card#me>;
+ acl:mode acl:Read, acl:Write, acl:Control.
+
+<#public>
+ a acl:Authorization;
+ acl:accessTo <https://alice.databox.me/docs/file2>;
+ acl:agentClass acl:AuthenticatedAgent;
+ acl:mode acl:Read.
+")))
+ (update-path
+ "/"
+ (lambda (main auxiliary)
+ (values /
+ `((,(string->uri "http://www.w3.org/ns/auth/acl#accessControl")
+ . ,/.acl))))
+ content-type contained static-content create delete)
+ (update-path
+ "/docs/"
+ (lambda (main auxiliary)
+ (values /docs/
+ `((,(string->uri "http://www.w3.org/ns/auth/acl#accessControl")
+ . ,/docs/.acl))))
+ content-type contained static-content create delete)
+ (update-path
+ "/docs/file1"
+ (lambda (main auxiliary)
+ (values /docs/file1
+ `((,(string->uri "http://www.w3.org/ns/auth/acl#accessControl")
+ . ,/docs/file1.acl))))
+ content-type contained static-content create delete)
+ (update-path
+ "/docs/file2"
+ (lambda (main auxiliary)
+ (values /docs/file2
+ `((,(string->uri "http://www.w3.org/ns/auth/acl#accessControl")
+ . ,/docs/file2.acl))))
+ content-type contained static-content create delete)
+ (update-path
+ "/private-docs/"
+ (lambda (main auxiliary)
+ (values /private-docs/ '()))
+ content-type contained static-content create delete)
+ (update-path
+ "/private-docs/file1"
+ (lambda (main auxiliary)
+ (values /private-docs/file1 '()))
+ content-type contained static-content create delete)
+ (update-path
+ "/private-docs/file2"
+ (lambda (main auxiliary)
+ (values /private-docs/file2 '()))
+ content-type contained static-content create delete)
+ (let ((server-name
+ (string->uri "https://alice.databox.me")))
+ ;; Who can access what?
+ ;; Alice: https://alice.databox.me/profile/card#me
+ ;; Bob: https://bob.databox.me/profile/card#me (authenticated)
+ ;; FBI: https://the-spy.databox.me/profile/card#me
+ ;; Anonymous
+ ;;
+ ;; Alice Bob FBI Anonymous
+ ;; / RWC X RW X
+ ;; /docs/ RWC R R R
+ ;; /docs/file1 RWC R R R
+ ;; /docs/file2 RWC R R X
+ ;; /private-docs/ RWC X X X
+ ;; /private-docs/file1 RWC X RW X
+ ;; /private-docs/file2 RWC X X X
+ (define (run-test path modes-alice modes-bob modes-fbi modes-anonymous)
+ (define (uri< a b)
+ (string< (uri->string a) (uri->string b)))
+ (let ((alice (wac-get-modes
+ server-name path
+ (string->uri "https://alice.databox.me/profile/card#me")
+ #:http-get http-get))
+ (bob (wac-get-modes
+ server-name path
+ (string->uri "https://bob.databox.me/profile/card#me")
+ #:http-get http-get))
+ (fbi (wac-get-modes
+ server-name path
+ (string->uri "https://the-spy.databox.me/profile/card#me")
+ #:http-get http-get))
+ (anonymous (wac-get-modes
+ server-name path
+ #f
+ #:http-get http-get)))
+ (unless (equal? alice
+ modes-alice)
+ (format (current-error-port)
+ "Alice’s modes for path ~s:\n expected:\n ~s\n got:\n ~s\n"
+ path
+ (map uri->string modes-alice)
+ (map uri->string alice))
+ (exit 2))
+ (unless (equal? bob
+ modes-bob)
+ (format (current-error-port)
+ "Bob’s modes for path ~s:\n expected:\n ~s\n got:\n ~s\n"
+ path
+ (map uri->string modes-bob)
+ (map uri->string bob))
+ (exit 3))
+ (unless (equal? fbi
+ modes-fbi)
+ (format (current-error-port)
+ "Spy’s modes for path ~s:\n expected:\n ~s\n got:\n ~s\n"
+ path
+ (map uri->string modes-fbi)
+ (map uri->string fbi))
+ (exit 4))
+ (unless (equal? anonymous
+ modes-anonymous)
+ (format (current-error-port)
+ "Anonymous modes for path ~s:\n expected:\n ~s\n got:\n ~s\n"
+ path
+ (map uri->string modes-anonymous)
+ (map uri->string anonymous))
+ (exit 5))))
+ (let ((read (string->uri "http://www.w3.org/ns/auth/acl#Read"))
+ (write (string->uri "http://www.w3.org/ns/auth/acl#Write"))
+ (control (string->uri "http://www.w3.org/ns/auth/acl#Control")))
+ (let ((RWC (list control read write))
+ (R (list read))
+ (RW (list read write))
+ (X '()))
+ (run-test "/" RWC X RW X)
+ (run-test "/docs/" RWC R R R)
+ (run-test "/docs/file1" RWC R R R)
+ (run-test "/docs/file2" RWC R R X)
+ (run-test "/private-docs/" RWC X X X)
+ (run-test "/private-docs/file1" RWC X RW X)
+ (run-test "/private-docs/file2" RWC X X X)))))))))