Skip to content

Instantly share code, notes, and snippets.

@burhanloey
Last active May 31, 2018 22:51
Show Gist options
  • Save burhanloey/205e27b1b91dcd7c04b4c6ae06ad230f to your computer and use it in GitHub Desktop.
Save burhanloey/205e27b1b91dcd7c04b4c6ae06ad230f to your computer and use it in GitHub Desktop.
Example of code implementing buddy middleware for async handlers
(ns myapp.buddy-async-middleware
(:require [buddy.auth.accessrules :refer [compile-access-rules success?
handle-error error]]
[buddy.auth.middleware :refer [authentication-request
authorization-error]]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; wrap-access-rules
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn- match-access-rules
"Copy pasted match-access-rules from buddy since it is private."
[accessrules request]
(reduce (fn [acc accessrule]
(let [matcher (:matcher accessrule)
match-result (matcher request)]
(when match-result
(reduced (assoc accessrule :match-params match-result)))))
nil
accessrules))
(defn- apply-matched-access-rule
"Copy pasted apply-matched-access-rule from buddy since it is private."
[match request]
{:pre [(map? match)
(contains? match :handler)]}
(let [handler (:handler match)
params (:match-params match)]
(-> request
(assoc :match-params params)
(handler))))
(defn wrap-access-rules
"Same with buddy's wrap-access-rules except for async handler.
TODO: Use buddy's async middleware once they implemented it."
[handler & [{:keys [policy rules] :or {policy :allow} :as opts}]]
(when (nil? rules)
(throw (IllegalArgumentException. "rules should not be empty.")))
(let [accessrules (compile-access-rules rules)]
(fn [request respond raise]
(if-let [match (match-access-rules accessrules request)]
(let [res (apply-matched-access-rule match request)]
(if (success? res)
(handler request respond raise)
(respond (handle-error res request (merge opts match)))))
(case policy
:allow (handler request respond raise)
:reject (respond (handle-error (error nil) request opts)))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; wrap-authentication
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn wrap-authentication
"Same with buddy's wrap-authentication except for async handler.
TODO: Use buddy's async middleware once they implemented it."
[handler & backends]
(fn [request respond raise]
(handler (apply authentication-request request backends) respond raise)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; wrap-authorization
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn wrap-authorization
"Same with buddy's wrap-authorization except for async handler.
TODO: Use buddy's async middleware once they implemented it."
[handler backend]
(fn [request respond raise]
(try
(handler request respond #(raise (authorization-error request % backend)))
(catch Exception e
(authorization-error request e backend)))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment