mirror of
https://github.com/penpot/penpot.git
synced 2025-01-10 08:50:57 -05:00
Merge remote-tracking branch 'origin/staging' into develop
This commit is contained in:
commit
b183dc3e62
3 changed files with 82 additions and 66 deletions
|
@ -14,48 +14,56 @@
|
||||||
[app.db :as db]
|
[app.db :as db]
|
||||||
[app.emails :as eml]
|
[app.emails :as eml]
|
||||||
[app.rpc.queries.profile :as profile]
|
[app.rpc.queries.profile :as profile]
|
||||||
|
[app.worker :as wrk]
|
||||||
[clojure.spec.alpha :as s]
|
[clojure.spec.alpha :as s]
|
||||||
[integrant.core :as ig]))
|
[integrant.core :as ig]
|
||||||
|
[promesa.core :as p]
|
||||||
|
[promesa.exec :as px]))
|
||||||
|
|
||||||
(declare send-feedback)
|
(declare ^:private send-feedback)
|
||||||
|
(declare ^:private handler)
|
||||||
|
|
||||||
(defmethod ig/pre-init-spec ::handler [_]
|
(defmethod ig/pre-init-spec ::handler [_]
|
||||||
(s/keys :req-un [::db/pool]))
|
(s/keys :req-un [::db/pool ::wrk/executor]))
|
||||||
|
|
||||||
(defmethod ig/init-key ::handler
|
(defmethod ig/init-key ::handler
|
||||||
[_ {:keys [pool] :as scfg}]
|
[_ {:keys [executor] :as cfg}]
|
||||||
(let [ftoken (cf/get :feedback-token ::no-token)
|
(let [ftoken (cf/get :feedback-token ::no-token)
|
||||||
enabled (contains? cf/flags :user-feedback)]
|
enabled? (contains? cf/flags :user-feedback)]
|
||||||
(fn [{:keys [profile-id] :as request}]
|
(if enabled?
|
||||||
(let [token (get-in request [:headers "x-feedback-token"])
|
(fn [request respond raise]
|
||||||
params (d/merge (:params request)
|
(-> (px/submit! executor #(handler cfg request))
|
||||||
(:body-params request))]
|
(p/then' respond)
|
||||||
|
(p/catch raise)))
|
||||||
|
(fn [_ _ raise]
|
||||||
|
(raise (ex/error :type :validation
|
||||||
|
:code :feedback-disabled
|
||||||
|
:hint "feedback module is disabled"))))))
|
||||||
|
|
||||||
(when-not enabled
|
(defn- handler
|
||||||
(ex/raise :type :validation
|
[{:keys [pool] :as cfg} {:keys [profile-id] :as request}]
|
||||||
:code :feedback-disabled
|
(let [ftoken (cf/get :feedback-token ::no-token)
|
||||||
:hint "feedback module is disabled"))
|
token (get-in request [:headers "x-feedback-token"])
|
||||||
|
params (d/merge (:params request)
|
||||||
|
(:body-params request))]
|
||||||
|
(cond
|
||||||
|
(uuid? profile-id)
|
||||||
|
(let [profile (profile/retrieve-profile-data pool profile-id)
|
||||||
|
params (assoc params :from (:email profile))]
|
||||||
|
(send-feedback pool profile params))
|
||||||
|
|
||||||
(cond
|
(= token ftoken)
|
||||||
(uuid? profile-id)
|
(send-feedback cfg nil params))
|
||||||
(let [profile (profile/retrieve-profile-data pool profile-id)
|
|
||||||
params (assoc params :from (:email profile))]
|
|
||||||
(when-not (:is-muted profile)
|
|
||||||
(send-feedback pool profile params)))
|
|
||||||
|
|
||||||
(= token ftoken)
|
{:status 204 :body ""}))
|
||||||
(send-feedback scfg nil params))
|
|
||||||
|
|
||||||
{:status 204 :body ""}))))
|
|
||||||
|
|
||||||
(s/def ::content ::us/string)
|
(s/def ::content ::us/string)
|
||||||
(s/def ::from ::us/email)
|
(s/def ::from ::us/email)
|
||||||
(s/def ::subject ::us/string)
|
(s/def ::subject ::us/string)
|
||||||
|
|
||||||
(s/def ::feedback
|
(s/def ::feedback
|
||||||
(s/keys :req-un [::from ::subject ::content]))
|
(s/keys :req-un [::from ::subject ::content]))
|
||||||
|
|
||||||
(defn send-feedback
|
(defn- send-feedback
|
||||||
[pool profile params]
|
[pool profile params]
|
||||||
(let [params (us/conform ::feedback params)
|
(let [params (us/conform ::feedback params)
|
||||||
destination (cf/get :feedback-destination)]
|
destination (cf/get :feedback-destination)]
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
[clojure.core.async :as a]
|
[clojure.core.async :as a]
|
||||||
[clojure.spec.alpha :as s]
|
[clojure.spec.alpha :as s]
|
||||||
[cuerdas.core :as str]
|
[cuerdas.core :as str]
|
||||||
|
[promesa.core :as p]
|
||||||
|
[promesa.exec :as px]
|
||||||
[integrant.core :as ig]
|
[integrant.core :as ig]
|
||||||
[lambdaisland.uri :as u]
|
[lambdaisland.uri :as u]
|
||||||
[promesa.exec :as px]))
|
[promesa.exec :as px]))
|
||||||
|
@ -79,53 +81,58 @@
|
||||||
(s/keys :req-un [::type ::name ::props ::timestamp ::profile-id]
|
(s/keys :req-un [::type ::name ::props ::timestamp ::profile-id]
|
||||||
:opt-un [::context]))
|
:opt-un [::context]))
|
||||||
|
|
||||||
(s/def ::frontend-events (s/every ::event))
|
(s/def ::frontend-events (s/every ::frontend-event))
|
||||||
|
|
||||||
(defmethod ig/init-key ::http-handler
|
(defmethod ig/init-key ::http-handler
|
||||||
[_ {:keys [executor pool] :as cfg}]
|
[_ {:keys [executor pool] :as cfg}]
|
||||||
(if (db/read-only? pool)
|
(if (or (db/read-only? pool) (not (contains? cf/flags :audit-log)))
|
||||||
(do
|
(do
|
||||||
(l/warn :hint "audit log http handler disabled, db is read-only")
|
(l/warn :hint "audit log http handler disabled or db is read-only")
|
||||||
(constantly {:status 204 :body ""}))
|
(fn [_ respond _]
|
||||||
(fn [{:keys [params profile-id] :as request}]
|
(respond {:status 204 :body ""})))
|
||||||
(when (contains? cf/flags :audit-log)
|
|
||||||
(let [events (->> (:events params)
|
|
||||||
(remove #(not= profile-id (:profile-id %)))
|
|
||||||
(us/conform ::frontend-events))
|
|
||||||
ip-addr (parse-client-ip request)
|
|
||||||
cfg (-> cfg
|
|
||||||
(assoc :source "frontend")
|
|
||||||
(assoc :events events)
|
|
||||||
(assoc :ip-addr ip-addr))]
|
|
||||||
|
|
||||||
(px/run! executor #(persist-http-events cfg))))
|
|
||||||
{:status 204 :body ""})))
|
(letfn [(handler [{:keys [params profile-id] :as request}]
|
||||||
|
(let [events (->> (:events params)
|
||||||
|
(remove #(not= profile-id (:profile-id %)))
|
||||||
|
(us/conform ::frontend-events))
|
||||||
|
|
||||||
|
ip-addr (parse-client-ip request)
|
||||||
|
cfg (-> cfg
|
||||||
|
(assoc :source "frontend")
|
||||||
|
(assoc :events events)
|
||||||
|
(assoc :ip-addr ip-addr))]
|
||||||
|
(persist-http-events cfg)))
|
||||||
|
|
||||||
|
(handle-error [cause]
|
||||||
|
(let [xdata (ex-data cause)]
|
||||||
|
(if (= :spec-validation (:code xdata))
|
||||||
|
(l/error ::l/raw (str "spec validation on persist-events:\n" (us/pretty-explain xdata)))
|
||||||
|
(l/error :hint "error on persist-events" :cause cause))))]
|
||||||
|
|
||||||
|
(fn [request respond raise]
|
||||||
|
;; Fire and forget, log error in case of errro
|
||||||
|
(-> (px/submit! executor #(handler request))
|
||||||
|
(p/catch handle-error))
|
||||||
|
|
||||||
|
(respond {:status 204 :body ""})))))
|
||||||
|
|
||||||
(defn- persist-http-events
|
(defn- persist-http-events
|
||||||
[{:keys [pool events ip-addr source] :as cfg}]
|
[{:keys [pool events ip-addr source] :as cfg}]
|
||||||
(try
|
(let [columns [:id :name :source :type :tracked-at :profile-id :ip-addr :props :context]
|
||||||
(let [columns [:id :name :source :type :tracked-at :profile-id :ip-addr :props :context]
|
prepare-xf (map (fn [event]
|
||||||
prepare-xf (map (fn [event]
|
[(uuid/next)
|
||||||
[(uuid/next)
|
(:name event)
|
||||||
(:name event)
|
source
|
||||||
source
|
(:type event)
|
||||||
(:type event)
|
(:timestamp event)
|
||||||
(:timestamp event)
|
(:profile-id event)
|
||||||
(:profile-id event)
|
(db/inet ip-addr)
|
||||||
(db/inet ip-addr)
|
(db/tjson (:props event))
|
||||||
(db/tjson (:props event))
|
(db/tjson (d/without-nils (:context event)))]))]
|
||||||
(db/tjson (d/without-nils (:context event)))]))
|
(when (seq events)
|
||||||
events (us/conform ::events events)]
|
(->> (into [] prepare-xf events)
|
||||||
(when (seq events)
|
(db/insert-multi! pool :audit-log columns)))))
|
||||||
(->> (into [] prepare-xf events)
|
|
||||||
(db/insert-multi! pool :audit-log columns))))
|
|
||||||
(catch Throwable e
|
|
||||||
(let [xdata (ex-data e)]
|
|
||||||
(if (= :spec-validation (:code xdata))
|
|
||||||
(l/error ::l/raw (str "spec validation on persist-events:\n"
|
|
||||||
(:explain xdata)))
|
|
||||||
(l/error :hint "error on persist-events"
|
|
||||||
:cause e))))))
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Collector
|
;; Collector
|
||||||
|
|
|
@ -135,7 +135,8 @@
|
||||||
:signature-max-age (dt/duration {:hours 24 :minutes 5})}
|
:signature-max-age (dt/duration {:hours 24 :minutes 5})}
|
||||||
|
|
||||||
:app.http.feedback/handler
|
:app.http.feedback/handler
|
||||||
{:pool (ig/ref :app.db/pool)}
|
{:pool (ig/ref :app.db/pool)
|
||||||
|
:executor (ig/ref [::default :app.worker/executor])}
|
||||||
|
|
||||||
:app.http.oauth/handler
|
:app.http.oauth/handler
|
||||||
{:rpc (ig/ref :app.rpc/rpc)
|
{:rpc (ig/ref :app.rpc/rpc)
|
||||||
|
@ -280,7 +281,7 @@
|
||||||
|
|
||||||
:app.loggers.audit/http-handler
|
:app.loggers.audit/http-handler
|
||||||
{:pool (ig/ref :app.db/pool)
|
{:pool (ig/ref :app.db/pool)
|
||||||
:executor (ig/ref [::default :app.worker/executor])}
|
:executor (ig/ref [::worker :app.worker/executor])}
|
||||||
|
|
||||||
:app.loggers.audit/collector
|
:app.loggers.audit/collector
|
||||||
{:pool (ig/ref :app.db/pool)
|
{:pool (ig/ref :app.db/pool)
|
||||||
|
|
Loading…
Reference in a new issue