From f170ca47c8e578452c1113c28a439756d56f3de0 Mon Sep 17 00:00:00 2001 From: Milton Reder Date: Wed, 8 Nov 2023 12:40:05 -0500 Subject: [PATCH] SQL-215 generic scanner function support --- .../pedestal/interceptor/xapi/statements.cljc | 22 +++++++++++ .../com/yetanalytics/lrs/pedestal/routes.cljc | 38 ++++++++++++------- 2 files changed, 46 insertions(+), 14 deletions(-) diff --git a/src/main/com/yetanalytics/lrs/pedestal/interceptor/xapi/statements.cljc b/src/main/com/yetanalytics/lrs/pedestal/interceptor/xapi/statements.cljc index d4b3d664..893ac17d 100644 --- a/src/main/com/yetanalytics/lrs/pedestal/interceptor/xapi/statements.cljc +++ b/src/main/com/yetanalytics/lrs/pedestal/interceptor/xapi/statements.cljc @@ -236,6 +236,28 @@ {:status 400 :body {:error {:message "No Statement Data Provided"}}}))))}) +(defn scan-attachments + "Scan attachment files with a user-provided function." + [file-scanner] + {:name ::scan-attachments + :enter + (fn [ctx] + (let [attachments (get-in ctx [:xapi :xapi.statements/attachments])] + (if-let [attachment-errors (some-> attachments + (->> (keep (fn [{:keys [content]}] + (file-scanner content)))) + not-empty)] + (do + (attachment/delete-attachments! attachments) + (assoc (chain/terminate ctx) + :response + {:status 400 + :body {:error {:message + (format "Scan failed, Errors: %s" + (cs/join ", " + (map :message attachment-errors)))}}})) + ctx)))}) + (def set-consistent-through {:name ::set-consistent-through :leave diff --git a/src/main/com/yetanalytics/lrs/pedestal/routes.cljc b/src/main/com/yetanalytics/lrs/pedestal/routes.cljc index c0088829..4055eb40 100644 --- a/src/main/com/yetanalytics/lrs/pedestal/routes.cljc +++ b/src/main/com/yetanalytics/lrs/pedestal/routes.cljc @@ -93,10 +93,14 @@ :path-prefix - defines the prefix from root for xAPI routes, default /xapi :wrap-interceptors - a vector of interceptors to apply to every route. The default vector includes an error interceptor which should be replaced - if this setting is provided." + if this setting is provided. + :file-scanner - a function that takes the content of any arbitrary + user-submitted file and returns nil if it is safe, or a map with :message + describing why it is unsafe. If unsafe the request will fail with a 400." [{:keys [lrs path-prefix - wrap-interceptors] + wrap-interceptors + file-scanner] :or {path-prefix "/xapi" wrap-interceptors [i/error-interceptor]}}] (let [lrs-i (i/lrs-interceptor lrs) @@ -150,19 +154,25 @@ statements/handle-get) :route-name :com.yetanalytics.lrs.xapi.statements/head] [(format "%s/statements" path-prefix) - :put (conj protected-interceptors - statements-i/set-consistent-through - (xapi-i/params-interceptor - :xapi.statements.PUT.request/params) - statements-i/parse-multiparts - statements-i/validate-request-statements - statements/handle-put)] + :put (-> protected-interceptors + (into [statements-i/set-consistent-through + (xapi-i/params-interceptor + :xapi.statements.PUT.request/params) + statements-i/parse-multiparts + statements-i/validate-request-statements]) + (cond-> + file-scanner + (conj (statements-i/scan-attachments file-scanner))) + (conj statements/handle-put))] [(format "%s/statements" path-prefix) - :post (conj protected-interceptors - statements-i/set-consistent-through - statements-i/parse-multiparts - statements-i/validate-request-statements - statements/handle-post)] + :post (-> protected-interceptors + (into [statements-i/set-consistent-through + statements-i/parse-multiparts + statements-i/validate-request-statements]) + (cond-> + file-scanner + (conj (statements-i/scan-attachments file-scanner))) + (conj statements/handle-post))] [(format "%s/statements" path-prefix) :any method-not-allowed :route-name :com.yetanalytics.lrs.xapi.statements/any]