I have created a custom route metadata handler, auth-rules
, for checking permissions. Sometimes
these permission checks require access to data in e.g. the response body. Accessing the data is done
before compojure-api validates and coerces the data, forcing me to validate it and thus re-implement
stuff done anyways by compojure-api.
This could be done by simply wrapping the route handler function in a permissions check, but I would
like to maintain this declarative approach to permission checking. Would it be
possible to have compojure-api run the response validation and coercion before executing this
permission handler, and also access the coerced data in the handler?
An example endpoint with custom permission handler:
(api/POST "/" {user-id :identity}
:auth-rules instrument/instrument-owner?
:summary "Create a new exercise session"
:body [exercise-session-data ::spec/exercise-session-data]
:return ::spec/exercise-session
(let [exercise-session (assoc exercise-session-data :user-id user-id)
id (db/create-exercise-session! exercise-session)]
(res/created nil (merge exercise-session id))))
Permission handler (where I'd like to access validated exercise-session-data as defined
in the body of the above endpoint):
(defn instrument-owner? [{user-id :identity
{:keys [instrument-id]} :body-params}]
(let [instrument (db/find-instrument-by-id {:id instrument-id})]
(= (:user-id instrument) user-id)))
auth-rules
implementation:
(defn- wrap-restricted [handler rule]
(rules/restrict handler {:handler rule
:on-error on-auth-error}))
(defmethod restructure-param :auth-rules
[_ rule acc]
(update-in acc [:middleware] conj [wrap-restricted rule]))
maybe you could implement it as a :middleware
instead? https://github.com/metosin/compojure-api/wiki/Middleware
The current solution is implemented as a route-specific middleware function. The problem is that I can't access the coerced params from a middleware function
in compojure-api.meta:
(defmethod restructure-param :coercion [_ coercion acc]
(-> acc
(assoc-in [:info :coercion] coercion)
(update-in [:middleware] conj [`mw/wrap-coercion coercion])))
maybe you can put your own coercion before the :auth-rules and remove the old one?That should work. Also, you can try to reorganize the middleware in the :auth-rules
restructuring.
Great, thanks for the quick help!