diff --git a/src/source/middleware/auth/core.clj b/src/source/middleware/auth/core.clj index bb5032d..2b7486c 100644 --- a/src/source/middleware/auth/core.clj +++ b/src/source/middleware/auth/core.clj @@ -4,7 +4,8 @@ [ring.util.response :as res] [source.services.bundles :as bundles] [source.db.honey :as db] - [taoensso.telemere :as t])) + [taoensso.telemere :as t] + [source.workers.bundles :as bundles-worker])) (defn create-session [user] (let [payload {:id (:id user) @@ -53,6 +54,27 @@ (res/response {:message "Unauthorized"}) (res/status 401)))))) +(defn wrap-integration-auth + "returns an unauthorized response if the integration id is not owned by this user and the user is not an admin" + [handler] + (fn [{:keys [ds user path-params] :as request}] + (let [bundle-id (try (Integer/parseInt (:id path-params)) (catch Exception _ nil))] + (cond + (nil? bundle-id) + (-> (res/response {:message "unauthorized"}) + (res/status 403)) + + (= (:type user) "admin") + (handler request) + + (and (= (:type user) "distributor") + (bundles-worker/user-owns-bundle? ds bundle-id (:id user))) + (handler request) + + :else + (-> (res/response {:message "unauthorized"}) + (res/status 403)))))) + (defn wrap-bundle-id "validates the bundle uuid in the query parameters of the request for unauthenticated users and attaches the bundle-id to the request" diff --git a/src/source/routes/integrations.clj b/src/source/routes/integrations.clj index 129e59a..df3a2cc 100644 --- a/src/source/routes/integrations.clj +++ b/src/source/routes/integrations.clj @@ -9,7 +9,8 @@ [source.routes.openapi :as api] [source.workers.schemas :as schemas] [source.db.honey :as hon] - [malli.util :as mu])) + [malli.util :as mu] + [source.db.util :as db.util])) (defn get {:summary "Get metadata of all integrations on the user account" @@ -62,3 +63,20 @@ :responses (api/success schemas/IntegrationTypes)} [{:keys [ds]}] (res/response (hon/find ds {:tname :integration-types}))) + +(defn refresh + {:summary "Force rerun of bundle job to refresh integration content" + :parameters (api/params :path [:map [:id {:description "Integration ID"} :int]]) + :responses (-> (api/success [:map [:message :string]]) + (api/unauthorized nil))} + [{:keys [ds path-params]}] + (let [bundle-id (:id path-params) + categories (->> (-> {:where [:= :bundle-id bundle-id]} + (db.util/tname :bundle-categories bundle-id)) + (hon/find ds) + (mapv #(assoc {} :id (:category-id %))))] + ((handlers/handler {:handler :update-bundle}) + {:ds ds + :args {:bundle-id bundle-id + :categories categories}}) + (res/response {:message "Successfully restarted bundle job."}))) diff --git a/src/source/routes/reitit.clj b/src/source/routes/reitit.clj index cab6fec..43dda91 100644 --- a/src/source/routes/reitit.clj +++ b/src/source/routes/reitit.clj @@ -74,7 +74,8 @@ [source.routes.job-stop :as job-stop] [source.routes.report :as report] [source.routes.approve-feed :as approve-feed] - [source.routes.reject-feed :as reject-feed])) + [source.routes.reject-feed :as reject-feed] + [source.middleware.auth.core :as auth])) (defn create-app [{:keys [ds js]}] (ring/ring-handler @@ -178,6 +179,8 @@ ["/:id" (-> (get integration/get) (post integration/post) (delete integration/delete))] + ["/:id/refresh" (-> (get integrations/refresh) + (rutil/mw auth/wrap-integration-auth))] ["/:id/categories" (-> (get integration-categories/get) (post integration-categories/post))] ["/:id/filter/feeds" (get integration-filter-feeds/get)] diff --git a/src/source/routes/util.clj b/src/source/routes/util.clj index 03569cb..07c2d06 100644 --- a/src/source/routes/util.clj +++ b/src/source/routes/util.clj @@ -117,3 +117,15 @@ :default-values true :options nil}) :middleware middleware}}) + +(defn middleware [& middlewares] + (let [[route-map mws] (apply parse-route-opts middlewares) + middleware (:middleware route-map) + mws (-> (or middleware []) + (concat mws))] + (->> mws + (mapv #(if (vector? %) % [%])) + (assoc route-map :middleware)))) + +(defn mw [& middlewares] + (apply middleware middlewares)) diff --git a/src/source/workers/bundles.clj b/src/source/workers/bundles.clj index 9ec696c..1b6caf3 100644 --- a/src/source/workers/bundles.clj +++ b/src/source/workers/bundles.clj @@ -2,7 +2,8 @@ (:require [source.db.honey :as hon] [honey.sql.helpers :as hsql] [source.db.util :as db.util] - [source.prandom.core :as prandom]) + [source.prandom.core :as prandom] + [pg.core :as pg]) (:import [java.time LocalDateTime] [java.time.format DateTimeFormatter])) @@ -111,6 +112,16 @@ :next-index (when (and next-index (< next-index total-size)) next-index)} :data limited-posts})) +(defn user-owns-bundle? [ds user-id bundle-id] + (-> + (pg/execute + ds + "SELECT EXISTS(SELECT 1 FROM bundles WHERE id = $1 AND user_id = $2) AS exists" + {:params [bundle-id + user-id]}) + (first) + (:exists))) + (comment (time (get-outgoing-posts (db.util/conn) {:bundle-id 14