summaryrefslogtreecommitdiff
path: root/src/scm/webid-oidc/resource-server.scm
diff options
context:
space:
mode:
Diffstat (limited to 'src/scm/webid-oidc/resource-server.scm')
-rw-r--r--src/scm/webid-oidc/resource-server.scm295
1 files changed, 44 insertions, 251 deletions
diff --git a/src/scm/webid-oidc/resource-server.scm b/src/scm/webid-oidc/resource-server.scm
index 65d64f0..95fa78a 100644
--- a/src/scm/webid-oidc/resource-server.scm
+++ b/src/scm/webid-oidc/resource-server.scm
@@ -20,6 +20,9 @@
#:use-module (webid-oidc jwk)
#:use-module (webid-oidc dpop-proof)
#:use-module (webid-oidc serve)
+ #:use-module (webid-oidc server endpoint)
+ #:use-module (webid-oidc server endpoint authentication)
+ #:use-module (webid-oidc server endpoint resource-server)
#:use-module ((webid-oidc server create) #:prefix ldp:)
#:use-module ((webid-oidc server read) #:prefix ldp:)
#:use-module ((webid-oidc server update) #:prefix ldp:)
@@ -49,6 +52,7 @@
#:use-module (ice-9 exceptions)
#:use-module (sxml simple)
#:use-module (srfi srfi-19)
+ #:use-module (srfi srfi-26)
#:use-module (oop goops)
#:duplicates (merge-generics)
#:declarative? #t
@@ -84,78 +88,6 @@
(handle endpoint request request-body))))
#:unwind? #t)))))
-(define (handle-errors f g)
- (call/ec
- (lambda (do-return)
- (define (return . args)
- (apply do-return args))
- (with-exception-handler
- (lambda (error)
- (g return error))
- (lambda ()
- (f return))
- #:unwind? #t))))
-
-(define (nonrdf-or-turtle server-uri request request-body)
- ;; If the request is an exotic RDF serialization
- ;; format, we want to convert it to Turtle,
- ;; otherwise we will consider it non-rdf.
- (convert '(text/turtle */*)
- server-uri
- (uri-path (request-uri request))
- (match (request-content-type request)
- ((or (? symbol? content-type)
- ((? symbol? content-type) _ ...))
- content-type))
- request-body))
-
-(define (serve-get return path if-match if-none-match content-type content etag headers user)
- (define (respond-normal)
- (return
- (build-response
- #:headers headers)
- content
- user))
- (if if-match
- ;; If the precondition failed, then we should respond with 412
- (with-exception-handler
- (lambda (error)
- (unless (precondition-failed? error)
- (raise-exception error))
- (return
- (build-response
- #:code 412
- #:reason-phrase (W_ "reason-phrase|Precondition Failed"))
- #f
- user))
- (lambda ()
- (check-precondition path if-match if-none-match etag)
- (respond-normal)))
- ;; If the precondition succeeds (if-none-match is effectively
- ;; invalid), we return 200
- (with-exception-handler
- (lambda (error)
- (unless (precondition-failed? error)
- (raise-exception error))
- (return
- (build-response
- #:code 304
- #:reason-phrase (W_ "reason-phrase|Not Modified")
- #:headers
- (filter
- (lambda (h)
- (case (car h)
- ((cache-control content-location date etag expires vary)
- #t)
- (else #f)))
- headers))
- #f
- user))
- (lambda ()
- (when if-none-match
- (check-precondition path if-match if-none-match etag))
- (respond-normal)))))
-
(define* (make-resource-server
#:key
(server-uri #f)
@@ -164,183 +96,44 @@
(unless owner
(fail (G_ "The owner is not defined.")))
(declare-link-header!)
- (unless authenticator
- (set! authenticator
- (make-authenticator
- #:server-uri server-uri)))
+ (define resource-server
+ (make <resource-server>
+ #:server-name server-uri
+ #:owner owner))
+ (define authenticator
+ (make <authenticator>
+ #:backend resource-server
+ #:server-uri server-uri))
(lambda (request request-body)
- (parameterize ((p:current-date ((p:current-date))) ;; Fix the date
- (web-locale request))
- (let ((user (authenticator request request-body)))
- (handle-errors
- (lambda (return)
- (let ((method (request-method request)))
- (case method
- ((GET HEAD OPTIONS)
- (receive (headers content)
- (ldp:read server-uri owner user
- (uri-path (request-uri request)))
- (let ((true-content-type
- (car (assq-ref headers 'content-type)))
- (other-headers
- (filter
- (lambda (h)
- (not (eq? (car h) 'content-type)))
- headers)))
- (receive (negociated-content-type
- negociated-content)
- (convert (request-accept request #f)
- server-uri
- (uri-path (request-uri request))
- true-content-type
- content)
- (serve-get
- return
- (uri-path (request-uri request))
- (request-if-match request)
- (request-if-none-match request)
- negociated-content-type
- negociated-content
- (car (assq-ref headers 'etag))
- (cons `(content-type ,negociated-content-type)
- other-headers)
- user)))))
- ((PUT)
- (receive (content-type content)
- (nonrdf-or-turtle server-uri request request-body)
- (unless content
- (return
- (build-response
- #:code 400
- #:reason-phrase (W_ "Bad Request"))
- ""
- user))
- (let ((updated
- (ldp:update server-uri owner user
- (uri-path (request-uri request))
- (request-if-match request)
- (request-if-none-match request)
- content-type
- content)))
- (return
- (build-response
- #:headers
- `((etag . (,(ldp:etag updated) . #f))))
- ""
- user))))
- ((POST)
- (receive (content-type content)
- (nonrdf-or-turtle server-uri request request-body)
- (unless content
- (return
- (build-response
- #:code 400
- #:reason-phrase (W_ "Bad Request"))
- ""
- user))
- (let ((types
- (map target-iri
- (filter
- (lambda (link)
- (equal? (relation-type link) "type"))
- (request-links request)))))
- (return
- (build-response
- #:code 201 #:reason-phrase (W_ "reason-phrase|Created")
- #:headers
- `((location . ,(ldp:create server-uri owner user
- (uri-path (request-uri request))
- types
- (assq-ref (request-headers request) 'slug)
- content-type
- content))))
- ""
- user))))
- ((DELETE)
- (ldp:delete server-uri owner user
- (uri-path (request-uri request))
- (request-if-match request)
- (request-if-none-match request))
- (return
- (build-response)
- ""
- user)))))
- (lambda (return error)
- (if (wac:cannot-fetch-group? error)
- (if (exception-with-message? error)
- (format (current-error-port)
- (G_ "~a: ignoring a group that cannot be fetched: ~a\n")
- (date->string ((p:current-date)))
- (exception-message error))
- (format (current-error-port)
- (G_ "~a: ignoring a group that cannot be fetched\n")
- (date->string ((p:current-date)))))
- (cond
- ((ldp:uri-slash-semantics-error? error)
- (return
- (build-response
- #:code 301
- #:reason-phrase (W_ "reason-phrase|Found")
- #:headers
- `((location
- . ,(build-uri
- (uri-scheme server-uri)
- #:userinfo (uri-userinfo server-uri)
- #:host (uri-host server-uri)
- #:port (uri-port server-uri)
- #:path (ldp:uri-slash-semantics-error-existing error)))))
- #f
- user))
- ((or (ldp:path-not-found? error)
- (ldp:auxiliary-resource-absent? error)
- (wac:forbidden? error))
- (if user
- ;; That’s a forbidden
- (return
- (build-response #:code 403 #:reason-phrase (W_ "reason-phrase|Forbidden"))
- #f
- user)
- (return
- (build-response #:code 401 #:reason-phrase (W_ "reason-phrase|Unauthorized")
- #:headers `((www-authenticate . ((DPoP)))))
- #f
- user)))
- ((ldp:cannot-delete-root? error)
- (return
- (build-response
- #:code 405
- #:reason-phrase (W_ "reason-phrase|Method Not Allowed"))
- #f
- user))
- ((or (ldp:container-not-empty? error)
- (ldp:incorrect-containment-triples? error)
- (ldp:path-is-auxiliary? error))
- (return
- (build-response
- #:code 409
- #:reason-phrase (W_ "reason-phrase|Conflict"))
- #f
- user))
- ((ldp:unsupported-media-type? error)
- (return
- (build-response
- #:code 415
- #:reason-phrase (W_ "reason-phrase|Unsupported Media Type"))
- #f
- user))
- ((precondition-failed? error)
- (return
- (build-response
- #:code 412
- #:reason-phrase (W_ "reason-phrase|Precondition Failed"))
- #f
- user))
- ((not-acceptable? error)
- (return
- (build-response
- #:code 406
- #:reason-phrase (W_ "reason-phrase|Not Acceptable"))
- #f
- user))
- (else
- (raise-exception error))))))))))
+ (let/ec return
+ (parameterize ((web-locale request))
+ (with-exception-handler
+ (lambda (exn)
+ (unless (web-exception? exn)
+ (raise-exception exn))
+ (return
+ (build-response
+ #:code (web-exception-code exn)
+ #:reason-phrase (web-exception-reason-phrase exn)
+ #:headers `((content-type application/xhtml+xml)))
+ (call-with-output-string
+ (cute sxml->xml
+ `(*TOP*
+ (*PI* xml "version=\"1.0\" encoding=\"utf-8\"")
+ (html (@ (xmlns "http://www.w3.org/1999/xhtml")
+ (xml:lang ,(W_ "xml-lang|en")))
+ (body
+ ,(call-with-input-string
+ (format #f (W_ "<h1>The resource server request failed</h1>"))
+ xml->sxml)
+ ,(if (user-message? exn)
+ (user-message-sxml exn)
+ (call-with-input-string
+ (format #f (W_ "<p>No more information.</p>"))
+ xml->sxml)))))
+ <>))))
+ (lambda ()
+ (receive (response response-body response-meta)
+ (handle authenticator request request-body)
+ (return response response-body)))
+ #:unwind? #t)))))