mirror of
https://github.com/penpot/penpot.git
synced 2026-05-10 10:38:17 +00:00
🚧 WIP
This commit is contained in:
parent
a04a6dd34c
commit
32627efb96
@ -804,12 +804,12 @@
|
||||
props (audit/profile->props profile)
|
||||
context (d/without-nils {:external-session-id (:external-session-id info)})]
|
||||
|
||||
(audit/submit! cfg {::audit/type "action"
|
||||
::audit/name "login-with-oidc"
|
||||
::audit/profile-id (:id profile)
|
||||
::audit/ip-addr (inet/parse-request request)
|
||||
::audit/props props
|
||||
::audit/context context})
|
||||
(audit/submit cfg {:type "action"
|
||||
:name "login-with-oidc"
|
||||
:profile-id (:id profile)
|
||||
:ip-addr (inet/parse-request request)
|
||||
:props props
|
||||
:context context})
|
||||
|
||||
(->> (redirect-to-verify-token token)
|
||||
(sxf request)))))
|
||||
|
||||
@ -34,6 +34,31 @@
|
||||
;; HELPERS
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(def ^:private safe-backend-context-keys
|
||||
#{:version
|
||||
:initiator
|
||||
:client-version
|
||||
:client-user-agent})
|
||||
|
||||
(def ^:privarte safe-frontend-context-keys
|
||||
#{:version
|
||||
:locale
|
||||
:browser
|
||||
:browser-version
|
||||
:engine
|
||||
:engine-version
|
||||
:os
|
||||
:os-version
|
||||
:device-type
|
||||
:device-arch
|
||||
:screen-width
|
||||
:screen-height
|
||||
:screen-color-depth
|
||||
:screen-orientation
|
||||
:event-origin
|
||||
:event-namespace
|
||||
:event-symbol})
|
||||
|
||||
(def profile-props
|
||||
[:id
|
||||
:is-active
|
||||
@ -122,15 +147,15 @@
|
||||
|
||||
(def ^:private schema:event
|
||||
[:map {:title "AuditEvent"}
|
||||
[::type ::sm/text]
|
||||
[::name ::sm/text]
|
||||
[::profile-id ::sm/uuid]
|
||||
[::ip-addr {:optional true} ::sm/text]
|
||||
[::props {:optional true} [:map-of :keyword :any]]
|
||||
[::context {:optional true} [:map-of :keyword :any]]
|
||||
[::tracked-at {:optional true} ::ct/inst]
|
||||
[::created-at {:optional true} ::ct/inst]
|
||||
[::source {:optional true} ::sm/text]
|
||||
[:type ::sm/text]
|
||||
[:name ::sm/text]
|
||||
[:profile-id ::sm/uuid]
|
||||
[:props [:map-of :keyword :any]]
|
||||
[:context [:map-of :keyword :any]]
|
||||
[:tracked-at ::ct/inst]
|
||||
[:created-at ::ct/inst]
|
||||
[:source ::sm/text]
|
||||
[:ip-addr {:optional true} ::sm/text]
|
||||
[::webhooks/event? {:optional true} ::sm/boolean]
|
||||
[::webhooks/batch-timeout {:optional true} ::ct/duration]
|
||||
[::webhooks/batch-key {:optional true}
|
||||
@ -142,55 +167,6 @@
|
||||
(def valid-event?
|
||||
(sm/validator schema:event))
|
||||
|
||||
(defn prepare-event
|
||||
[cfg mdata params result]
|
||||
(let [resultm (meta result)
|
||||
request (-> params meta ::http/request)
|
||||
profile-id (or (::profile-id resultm)
|
||||
(:profile-id result)
|
||||
(::rpc/profile-id params)
|
||||
uuid/zero)
|
||||
|
||||
props (-> (or (::replace-props resultm)
|
||||
(merge params (::props resultm)))
|
||||
(clean-props))
|
||||
|
||||
context (merge (::context resultm)
|
||||
(prepare-context-from-request request))
|
||||
ip-addr (inet/parse-request request)
|
||||
module (get cfg ::rpc/module)]
|
||||
|
||||
{::type (or (::type resultm)
|
||||
(::rpc/type cfg))
|
||||
::name (or (::name resultm)
|
||||
(let [sname (::sv/name mdata)]
|
||||
(if (not= module "main")
|
||||
(str module "-" sname)
|
||||
sname)))
|
||||
|
||||
::profile-id profile-id
|
||||
::ip-addr ip-addr
|
||||
::props props
|
||||
::context context
|
||||
|
||||
;; NOTE: for batch-key lookup we need the params as-is
|
||||
;; because the rpc api does not need to know the
|
||||
;; audit/webhook specific object layout.
|
||||
::rpc/params params
|
||||
|
||||
::webhooks/batch-key
|
||||
(or (::webhooks/batch-key mdata)
|
||||
(::webhooks/batch-key resultm))
|
||||
|
||||
::webhooks/batch-timeout
|
||||
(or (::webhooks/batch-timeout mdata)
|
||||
(::webhooks/batch-timeout resultm))
|
||||
|
||||
::webhooks/event?
|
||||
(or (::webhooks/event? mdata)
|
||||
(::webhooks/event? resultm)
|
||||
false)}))
|
||||
|
||||
(defn- prepare-context-from-request
|
||||
"Prepare backend event context from request"
|
||||
[request]
|
||||
@ -211,33 +187,27 @@
|
||||
:client-version client-version
|
||||
:version (:full cf/version)})))
|
||||
|
||||
(defn event-from-rpc-params
|
||||
"Create a base event skeleton with pre-filled some important
|
||||
data that can be extracted from RPC params object"
|
||||
[params]
|
||||
(let [context (some-> params meta ::http/request prepare-context-from-request)
|
||||
event {::type "action"
|
||||
::profile-id (or (::rpc/profile-id params) uuid/zero)
|
||||
::ip-addr (::rpc/ip-addr params)}]
|
||||
(cond-> event
|
||||
(some? context)
|
||||
(assoc ::context context))))
|
||||
(def ^:private event-keys
|
||||
#{:id
|
||||
:name
|
||||
:type
|
||||
:profile-id
|
||||
:ip-addr
|
||||
:context
|
||||
:props
|
||||
:context
|
||||
:source
|
||||
:tracked-at
|
||||
:created-at})
|
||||
|
||||
(defn- event->params
|
||||
[event]
|
||||
(let [params {:id (uuid/next)
|
||||
:name (::name event)
|
||||
:type (::type event)
|
||||
:profile-id (::profile-id event)
|
||||
:ip-addr (::ip-addr event)
|
||||
:context (::context event {})
|
||||
:props (::props event {})
|
||||
:source "backend"}
|
||||
tnow (::tracked-at event)]
|
||||
|
||||
(cond-> params
|
||||
(some? tnow)
|
||||
(assoc :tracked-at tnow))))
|
||||
(defn- append-audit-entry
|
||||
[cfg params]
|
||||
(let [params (-> params
|
||||
(update :props db/tjson)
|
||||
(update :context db/tjson)
|
||||
(update :ip-addr db/inet))
|
||||
params (select-keys params event-keys)]
|
||||
(db/insert! cfg :audit-log params)))
|
||||
|
||||
(def ^:private xf:filter-telemetry-props
|
||||
"Transducer that keeps only map entries whose values are UUIDs."
|
||||
@ -245,68 +215,54 @@
|
||||
(and (simple-keyword? k)
|
||||
(or (uuid? v) (boolean? v) (number? v))))))
|
||||
|
||||
(defn filter-telemetry-props
|
||||
"Return only UUID-valued keys from a props map. This preserves
|
||||
object relations while maintaining anonymity."
|
||||
[props]
|
||||
(into {} xf:filter-telemetry-props props))
|
||||
|
||||
(defn- append-audit-entry
|
||||
[cfg params]
|
||||
(let [params (-> params
|
||||
(update :props db/tjson)
|
||||
(update :context db/tjson)
|
||||
(update :ip-addr db/inet))]
|
||||
(db/insert! cfg :audit-log params)))
|
||||
|
||||
(defn- get-telemetry-context
|
||||
"Get a telemetry ready safe context"
|
||||
[{:keys [context]}]
|
||||
(select-keys context [:initiator
|
||||
:version
|
||||
:client-version
|
||||
:client-user-agent]))
|
||||
|
||||
(defn- get-telemetry-props
|
||||
"A telemetry specific safe props"
|
||||
[{:keys [name props] :as params}]
|
||||
(defn- filter-telemetry-props
|
||||
[{:keys [source name props] :as params}]
|
||||
(cond
|
||||
(or (= name "login-with-oidc")
|
||||
(= name "login-with-password")
|
||||
(= name "register-profile")
|
||||
(= name "update-profile"))
|
||||
(-> (select-keys props profile-props)
|
||||
(filter-telemetry-props)
|
||||
(assoc :lang (:lang props))
|
||||
(assoc :auth-backend (:auth-backend props))
|
||||
(assoc :email-domain (email/get-domain (:email props)))
|
||||
(d/without-nils))
|
||||
(and (= source "backend")
|
||||
(or (= name "login-with-oidc")
|
||||
(= name "login-with-password")
|
||||
(= name "register-profile")
|
||||
(= name "update-profile")))
|
||||
(let [props (select-keys props profile-props)
|
||||
props (into {} xf:filter-telemetry-props props)
|
||||
props (-> props
|
||||
(assoc :lang (:lang props))
|
||||
(assoc :auth-backend (:auth-backend props))
|
||||
(assoc :email-domain (email/get-domain (:email props)))
|
||||
(d/without-nils))]
|
||||
(assoc params :props props))
|
||||
|
||||
:else
|
||||
(filter-telemetry-props props)))
|
||||
(let [props (into {} xf:filter-telemetry-props props)]
|
||||
(assoc params :props props))))
|
||||
|
||||
(defn- handle-event!
|
||||
(defn filter-telemetry-context
|
||||
[{:keys [source context] :as params}]
|
||||
(let [context (case source
|
||||
"backend" (select-keys context safe-backend-context-keys)
|
||||
"frontend" (select-keys context safe-frontend-context-keys)
|
||||
{})]
|
||||
(assoc params :context context)))
|
||||
|
||||
(defn- process-event
|
||||
[cfg event]
|
||||
(let [tnow (ct/now)
|
||||
params (-> (event->params event)
|
||||
(assoc :created-at tnow)
|
||||
(update :tracked-at #(or % tnow)))]
|
||||
(let [params (normalize-event event)]
|
||||
|
||||
(when (contains? cf/flags :audit-log-logger)
|
||||
(l/log! ::l/logger "app.audit"
|
||||
::l/level :info
|
||||
:profile-id (str (::profile-id event))
|
||||
:ip-addr (str (::ip-addr event))
|
||||
:type (::type event)
|
||||
:name (::name event)
|
||||
:props (json/encode (::props event) :key-fn json/write-camel-key)
|
||||
:context (json/encode (::context event) :key-fn json/write-camel-key)))
|
||||
:profile-id (str (:profile-id event))
|
||||
:ip-addr (str (:ip-addr event))
|
||||
:type (:type event)
|
||||
:name (:name event)
|
||||
:props (json/encode (:props event) :key-fn json/write-camel-key)
|
||||
:context (json/encode (:context event) :key-fn json/write-camel-key)))
|
||||
|
||||
(if (contains? cf/flags :audit-log)
|
||||
;; NOTE: this operation may cause primary key conflicts on inserts
|
||||
;; because of the timestamp precission (two concurrent requests), in
|
||||
;; this case we just retry the operation.
|
||||
(append-audit-entry cfg params)
|
||||
(append-audit-entry cfg event)
|
||||
(when cf/telemetry-enabled?
|
||||
;; NOTE: this operation may cause primary key conflicts on inserts
|
||||
;; because of the timestamp precission (two concurrent requests), in
|
||||
@ -320,15 +276,14 @@
|
||||
;; kept: initiator, version, client-version and client-user-agent.
|
||||
;; Timestamps are truncated to day precision to avoid leaking exact
|
||||
;; event timing.
|
||||
(let [event-name (get params :name)
|
||||
(let [event-name (get event :name)
|
||||
tday (ct/truncate tnow :days)
|
||||
params (-> params
|
||||
(assoc :source "telemetry:backend")
|
||||
(assoc :props (get-telemetry-props params))
|
||||
(assoc :context (get-telemetry-context params))
|
||||
(assoc :ip-addr (db/inet "0.0.0.0"))
|
||||
(assoc :created-at tday)
|
||||
(assoc :tracked-at tday))]
|
||||
event (-> event
|
||||
(filter-telemetry-props)
|
||||
(filter-telemetry-context)
|
||||
(update :created-at ct/truncate :days)
|
||||
(update :tracked-at ct/truncate :days)
|
||||
(assoc :ip-addr "0.0.0.0"))]
|
||||
(append-audit-entry cfg params))))
|
||||
|
||||
(when (and (contains? cf/flags :webhooks)
|
||||
@ -356,31 +311,117 @@
|
||||
(dissoc :type)))))))
|
||||
params))
|
||||
|
||||
(defn submit!
|
||||
"Submit audit event to the collector."
|
||||
(defn- or-ts-now
|
||||
[o]
|
||||
(if (inst? o) o (ct/now)))
|
||||
|
||||
(defn submit*
|
||||
"A public API, lower-leve lhan submit, assumes all required fields are filled"
|
||||
[cfg event]
|
||||
(try
|
||||
(let [event (-> (d/without-nils event)
|
||||
(check-event))
|
||||
cfg (-> cfg
|
||||
(assoc ::rtry/when rtry/conflict-exception?)
|
||||
(assoc ::rtry/max-retries 6)
|
||||
(assoc ::rtry/label "persist-audit-log"))]
|
||||
(rtry/invoke! cfg db/tx-run! handle-event! event))
|
||||
(let [event (check-event event)
|
||||
cfg (-> cfg
|
||||
(assoc ::rtry/when rtry/conflict-exception?)
|
||||
(assoc ::rtry/max-retries 6)
|
||||
(assoc ::rtry/label "persist-audit-log"))]
|
||||
(rtry/invoke! cfg db/tx-run! process-event event))
|
||||
(catch Throwable cause
|
||||
(l/error :hint "unexpected error processing event" :cause cause))))
|
||||
|
||||
(defn insert!
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; PUBLIC API
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn prepare-rpc-event
|
||||
[cfg mdata params result]
|
||||
(let [resultm (meta result)
|
||||
request (-> params meta ::http/request)
|
||||
profile-id (or (::profile-id resultm)
|
||||
(:profile-id result)
|
||||
(::rpc/profile-id params)
|
||||
uuid/zero)
|
||||
|
||||
props (-> (or (::replace-props resultm)
|
||||
(merge params (::props resultm)))
|
||||
(clean-props))
|
||||
|
||||
context (merge (::context resultm)
|
||||
(prepare-context-from-request request))
|
||||
ip-addr (inet/parse-request request)
|
||||
module (get cfg ::rpc/module)]
|
||||
|
||||
{:type (or (::type resultm)
|
||||
(::rpc/type cfg))
|
||||
:name (or (::name resultm)
|
||||
(let [sname (::sv/name mdata)]
|
||||
(if (not= module "main")
|
||||
(str module "-" sname)
|
||||
sname)))
|
||||
|
||||
:profile-id profile-id
|
||||
:ip-addr ip-addr
|
||||
:props props
|
||||
:context context
|
||||
|
||||
:created-at (::rpc/request-at params)
|
||||
:tracked-at (::rpc/request-at params)
|
||||
|
||||
;; NOTE: for batch-key lookup we need the params as-is
|
||||
;; because the rpc api does not need to know the
|
||||
;; audit/webhook specific object layout.
|
||||
::rpc/params params
|
||||
|
||||
::webhooks/batch-key
|
||||
(or (::webhooks/batch-key mdata)
|
||||
(::webhooks/batch-key resultm))
|
||||
|
||||
::webhooks/batch-timeout
|
||||
(or (::webhooks/batch-timeout mdata)
|
||||
(::webhooks/batch-timeout resultm))
|
||||
|
||||
::webhooks/event?
|
||||
(or (::webhooks/event? mdata)
|
||||
(::webhooks/event? resultm)
|
||||
false)}))
|
||||
|
||||
(defn event-from-rpc-params
|
||||
"Create a base event skeleton with pre-filled some important
|
||||
data that can be extracted from RPC params object"
|
||||
[params]
|
||||
(let [context (some-> params meta ::http/request prepare-context-from-request)
|
||||
event {:type "action"
|
||||
:profile-id (::rpc/profile-id params)
|
||||
:created-at (::rpc/request-at params)
|
||||
:tracked-at (::rpc/request-at params)
|
||||
:ip-addr (::rpc/ip-addr params)}]
|
||||
(cond-> event
|
||||
(some? context)
|
||||
(assoc :context context))))
|
||||
|
||||
(defn submit
|
||||
"Submit an event to be registered under audit-log subsystem"
|
||||
[cfg event]
|
||||
(let [tnow (ct/now)
|
||||
event (-> event
|
||||
(assoc :created-at tnow)
|
||||
(update :tracked-at or tnow)
|
||||
(update :ip-addr or "0.0.0.0")
|
||||
(assoc :source "backend")
|
||||
(d/without-nils))]
|
||||
(submit* cfg event)))
|
||||
|
||||
(defn insert
|
||||
"Submit audit event to the collector, intended to be used only from
|
||||
command line helpers because this skips all webhooks and telemetry
|
||||
logic."
|
||||
[cfg event]
|
||||
(when (contains? cf/flags :audit-log)
|
||||
(let [event (-> (d/without-nils event)
|
||||
(let [tnow (ct/now)
|
||||
event (-> event
|
||||
(assoc :created-at tnow)
|
||||
(update :tracked-at or tnow)
|
||||
(update :profile-id or uuid/zero)
|
||||
(assoc :source "backend")
|
||||
(select-keys event-keys)
|
||||
(check-event))]
|
||||
(db/run! cfg (fn [cfg]
|
||||
(let [tnow (ct/now)
|
||||
params (-> (event->params event)
|
||||
(assoc :created-at tnow)
|
||||
(update :tracked-at #(or % tnow)))]
|
||||
(append-audit-entry cfg params)))))))
|
||||
(db/run! cfg append-audit-entry params))))
|
||||
|
||||
@ -70,14 +70,14 @@
|
||||
(fn [{:keys [props] :as task}]
|
||||
|
||||
(let [items (lookup-webhooks cfg props)
|
||||
event {::audit/profile-id (:profile-id props)
|
||||
::audit/name "webhook"
|
||||
::audit/type "trigger"
|
||||
::audit/props {:name (get props :name)
|
||||
:event-id (get props :id)
|
||||
:total-affected (count items)}}]
|
||||
event {:profile-id (:profile-id props)
|
||||
:name "webhook"
|
||||
:type "trigger"
|
||||
:props {:name (get props :name)
|
||||
:event-id (get props :id)
|
||||
:total-affected (count items)}}]
|
||||
|
||||
(audit/insert! cfg event)
|
||||
(audit/insert cfg event)
|
||||
|
||||
(when items
|
||||
(l/trc :hint "webhooks found for event" :total (count items))
|
||||
|
||||
@ -161,12 +161,13 @@
|
||||
(defn- wrap-audit
|
||||
[_ f mdata]
|
||||
(if (or (contains? cf/flags :webhooks)
|
||||
(contains? cf/flags :audit-log))
|
||||
(contains? cf/flags :audit-log)
|
||||
(contains? cf/flags :telemetry))
|
||||
(if-not (::audit/skip mdata)
|
||||
(fn [cfg params]
|
||||
(let [result (f cfg params)]
|
||||
(->> (audit/prepare-event cfg mdata params result)
|
||||
(audit/submit! cfg))
|
||||
(->> (audit/prepare-rpc-event cfg mdata params result)
|
||||
(audit/submit* cfg))
|
||||
result))
|
||||
f)
|
||||
f))
|
||||
|
||||
@ -38,31 +38,31 @@
|
||||
:context])
|
||||
|
||||
(defn- event->row [event]
|
||||
[(::audit/id event)
|
||||
(::audit/name event)
|
||||
(::audit/source event)
|
||||
(::audit/type event)
|
||||
(::audit/tracked-at event)
|
||||
(::audit/created-at event)
|
||||
(::audit/profile-id event)
|
||||
(db/inet (::audit/ip-addr event))
|
||||
(db/tjson (::audit/props event))
|
||||
(db/tjson (d/without-nils (::audit/context event)))])
|
||||
[(:id event)
|
||||
(:name event)
|
||||
(:source event)
|
||||
(:type event)
|
||||
(:tracked-at event)
|
||||
(:created-at event)
|
||||
(:profile-id event)
|
||||
(db/inet (:ip-addr event))
|
||||
(db/tjson (:props event))
|
||||
(db/tjson (d/without-nils (:context event)))])
|
||||
|
||||
(defn- adjust-timestamp
|
||||
[{:keys [::audit/tracked-at ::audit/created-at] :as event}]
|
||||
[{:keys [tracked-at created-at] :as event}]
|
||||
(let [margin (inst-ms (ct/diff tracked-at created-at))]
|
||||
(if (or (neg? margin)
|
||||
(> margin 3600000))
|
||||
;; If event is in future or lags more than 1 hour, we reasign
|
||||
;; tracked-at to the server creation date
|
||||
(-> event
|
||||
(assoc ::audit/tracked-at created-at)
|
||||
(update ::audit/context assoc :original-tracked-at tracked-at))
|
||||
(assoc :tracked-at created-at)
|
||||
(update :context assoc :original-tracked-at tracked-at))
|
||||
event)))
|
||||
|
||||
(defn- exception-event?
|
||||
[{:keys [::audit/type ::audit/name] :as ev}]
|
||||
[{:keys [type name] :as ev}]
|
||||
(and (= "action" type)
|
||||
(or (= "unhandled-exception" name)
|
||||
(= "exception-page" name))))
|
||||
@ -72,78 +72,39 @@
|
||||
(map adjust-timestamp)
|
||||
(map event->row)))
|
||||
|
||||
(defn- get-events
|
||||
(defn- prepare-events
|
||||
[{:keys [::rpc/request-at ::rpc/profile-id events] :as params}]
|
||||
(let [request (-> params meta ::http/request)
|
||||
ip-addr (inet/parse-request request)
|
||||
|
||||
xform (map (fn [event]
|
||||
{::audit/id (uuid/next)
|
||||
::audit/type (:type event)
|
||||
::audit/name (:name event)
|
||||
::audit/props (:props event)
|
||||
::audit/context (:context event)
|
||||
::audit/profile-id profile-id
|
||||
::audit/ip-addr ip-addr
|
||||
::audit/source "frontend"
|
||||
::audit/tracked-at (:timestamp event)
|
||||
::audit/created-at request-at}))]
|
||||
{:id (uuid/next)
|
||||
:type (:type event)
|
||||
:name (:name event)
|
||||
:props (:props event)
|
||||
:context (:context event)
|
||||
:profile-id profile-id
|
||||
:ip-addr ip-addr
|
||||
:source "frontend"
|
||||
:tracked-at (:timestamp event)
|
||||
:created-at request-at}))]
|
||||
|
||||
(sequence xform events)))
|
||||
|
||||
;; Context keys from the frontend that are safe to retain for telemetry:
|
||||
;; they describe the browser/OS environment but cannot identify a user.
|
||||
;; Session-linking keys (session, external-session-id) and file-specific
|
||||
;; stats (file-stats) are intentionally excluded.
|
||||
(def ^:private safe-context-keys
|
||||
#{:version
|
||||
:locale
|
||||
:browser
|
||||
:browser-version
|
||||
:engine
|
||||
:engine-version
|
||||
:os
|
||||
:os-version
|
||||
:device-type
|
||||
:device-arch
|
||||
:screen-width
|
||||
:screen-height
|
||||
:screen-color-depth
|
||||
:screen-orientation
|
||||
:event-origin
|
||||
:event-namespace
|
||||
:event-symbol})
|
||||
|
||||
(defn- filter-safe-context
|
||||
"Return only the anonymous, non-identifying context fields from an
|
||||
event context map. Any key not in `safe-context-keys` is dropped."
|
||||
[ctx]
|
||||
(select-keys ctx safe-context-keys))
|
||||
|
||||
(def ^:private xf:map-telemetry-event-row
|
||||
(comp
|
||||
(map adjust-timestamp)
|
||||
(map (fn [event]
|
||||
(let [tday (-> (::audit/created-at event)
|
||||
(ct/truncate :days))
|
||||
safe-props (-> (::audit/props event {})
|
||||
(audit/filter-telemetry-props))
|
||||
safe-context (-> (::audit/context event)
|
||||
(select-keys safe-context-keys))]
|
||||
[(::audit/id event)
|
||||
(::audit/name event)
|
||||
"telemetry:frontend"
|
||||
(::audit/type event)
|
||||
tday
|
||||
tday
|
||||
(::audit/profile-id event)
|
||||
(db/inet "0.0.0.0")
|
||||
(db/tjson safe-props)
|
||||
(db/tjson safe-context)])))))
|
||||
(-> event
|
||||
(update :created-at ct/truncate :days)
|
||||
(update :tracked-at ct/truncate :days)
|
||||
(assoc :ip-addr "0.0.0.0")
|
||||
(audit/filter-telemetry-props)
|
||||
(audit/filter-telemetry-context))))
|
||||
(map event->row)))
|
||||
|
||||
(defn- handle-events
|
||||
[{:keys [::db/pool] :as cfg} params]
|
||||
(let [events (get-events params)]
|
||||
(let [events (prepare-events params)]
|
||||
|
||||
;; Look for error reports and save them on internal reports table
|
||||
(when-let [events (->> events
|
||||
|
||||
@ -425,10 +425,10 @@
|
||||
(doseq [file-id result]
|
||||
(let [props (assoc props :id file-id)
|
||||
event (-> (audit/event-from-rpc-params params)
|
||||
(assoc ::audit/profile-id profile-id)
|
||||
(assoc ::audit/name "create-file")
|
||||
(assoc ::audit/props props))]
|
||||
(audit/submit! cfg event))))))
|
||||
(assoc :profile-id profile-id)
|
||||
(assoc :name "create-file")
|
||||
(assoc :props props))]
|
||||
(audit/submit cfg event))))))
|
||||
|
||||
result))
|
||||
|
||||
|
||||
@ -156,9 +156,9 @@
|
||||
"update-team-invitation"
|
||||
"create-team-invitation")
|
||||
event (-> (audit/event-from-rpc-params params)
|
||||
(assoc ::audit/name evname)
|
||||
(assoc ::audit/props props))]
|
||||
(audit/submit! cfg event))
|
||||
(assoc :name evname)
|
||||
(assoc :props props))]
|
||||
(audit/submit cfg event))
|
||||
|
||||
(when (allow-invitation-emails? member)
|
||||
(eml/send! {::eml/conn conn
|
||||
@ -410,9 +410,9 @@
|
||||
|
||||
(let [props {:name name :features features}
|
||||
event (-> (audit/event-from-rpc-params params)
|
||||
(assoc ::audit/name "create-team")
|
||||
(assoc ::audit/props props))]
|
||||
(audit/submit! cfg event))
|
||||
(assoc :name "create-team")
|
||||
(assoc :props props))]
|
||||
(audit/submit cfg event))
|
||||
|
||||
;; Create invitations for all provided emails.
|
||||
(let [profile (db/get-by-id conn :profile profile-id)
|
||||
|
||||
@ -173,24 +173,22 @@
|
||||
:role (:role claims)
|
||||
:invitation-id (:id invitation)}]
|
||||
|
||||
(audit/submit!
|
||||
cfg
|
||||
(-> (audit/event-from-rpc-params params)
|
||||
(assoc ::audit/name "accept-team-invitation")
|
||||
(assoc ::audit/props props)))
|
||||
(audit/submit cfg
|
||||
(-> (audit/event-from-rpc-params params)
|
||||
(assoc :name "accept-team-invitation")
|
||||
(assoc :props props)))
|
||||
|
||||
;; NOTE: Backward compatibility; old invitations can
|
||||
;; have the `created-by` to be nil; so in this case we
|
||||
;; don't submit this event to the audit-log
|
||||
(when-let [created-by (:created-by invitation)]
|
||||
(audit/submit!
|
||||
cfg
|
||||
(-> (audit/event-from-rpc-params params)
|
||||
(assoc ::audit/profile-id created-by)
|
||||
(assoc ::audit/name "accept-team-invitation-from")
|
||||
(assoc ::audit/props (assoc props
|
||||
:profile-id (:id profile)
|
||||
:email (:email profile))))))
|
||||
(audit/submit cfg
|
||||
(-> (audit/event-from-rpc-params params)
|
||||
(assoc :profile-id created-by)
|
||||
(assoc :name "accept-team-invitation-from")
|
||||
(assoc :props (assoc props
|
||||
:profile-id (:id profile)
|
||||
:email (:email profile))))))
|
||||
|
||||
(accept-invitation cfg claims invitation profile)
|
||||
(assoc claims :state :created))
|
||||
|
||||
@ -553,14 +553,13 @@
|
||||
(let [file-id (h/parse-uuid file-id)
|
||||
tnow (ct/now)]
|
||||
|
||||
(audit/insert! main/system
|
||||
{::audit/name "delete-file"
|
||||
::audit/type "action"
|
||||
::audit/profile-id uuid/zero
|
||||
::audit/props {:id file-id}
|
||||
::audit/context {:triggered-by "srepl"
|
||||
:cause "explicit call to delete-file!"}
|
||||
::audit/tracked-at tnow})
|
||||
(audit/insert main/system
|
||||
{:name "delete-file"
|
||||
:type "action"
|
||||
:props {:id file-id}
|
||||
:context {:triggered-by "srepl"
|
||||
:cause "explicit call to delete-file!"}
|
||||
:tracked-at tnow})
|
||||
(wrk/invoke! (-> main/system
|
||||
(assoc ::wrk/task :delete-object)
|
||||
(assoc ::wrk/params {:object :file
|
||||
@ -578,15 +577,12 @@
|
||||
{:id file-id}
|
||||
{::db/remove-deleted false
|
||||
::sql/columns [:id :name]})]
|
||||
(audit/insert! system
|
||||
{::audit/name "restore-file"
|
||||
::audit/type "action"
|
||||
::audit/profile-id uuid/zero
|
||||
::audit/props file
|
||||
::audit/context {:triggered-by "srepl"
|
||||
:cause "explicit call to restore-file!"}
|
||||
::audit/tracked-at (ct/now)})
|
||||
|
||||
(audit/insert system
|
||||
{:name "restore-file"
|
||||
:type "action"
|
||||
:props file
|
||||
:context {:triggered-by "srepl"
|
||||
:cause "explicit call to restore-file!"}})
|
||||
|
||||
(#'files/restore-file conn file-id))
|
||||
:restored))))
|
||||
@ -597,14 +593,13 @@
|
||||
(let [project-id (h/parse-uuid project-id)
|
||||
tnow (ct/now)]
|
||||
|
||||
(audit/insert! main/system
|
||||
{::audit/name "delete-project"
|
||||
::audit/type "action"
|
||||
::audit/profile-id uuid/zero
|
||||
::audit/props {:id project-id}
|
||||
::audit/context {:triggered-by "srepl"
|
||||
:cause "explicit call to delete-project!"}
|
||||
::audit/tracked-at tnow})
|
||||
(audit/insert main/system
|
||||
{:name "delete-project"
|
||||
:type "action"
|
||||
:props {:id project-id}
|
||||
:context {:triggered-by "srepl"
|
||||
:cause "explicit call to delete-project!"}
|
||||
:tracked-at tnow})
|
||||
|
||||
(wrk/invoke! (-> main/system
|
||||
(assoc ::wrk/task :delete-object)
|
||||
@ -635,14 +630,12 @@
|
||||
(when-let [project (db/get* system :project
|
||||
{:id project-id}
|
||||
{::db/remove-deleted false})]
|
||||
(audit/insert! system
|
||||
{::audit/name "restore-project"
|
||||
::audit/type "action"
|
||||
::audit/profile-id uuid/zero
|
||||
::audit/props project
|
||||
::audit/context {:triggered-by "srepl"
|
||||
:cause "explicit call to restore-team!"}
|
||||
::audit/tracked-at (ct/now)})
|
||||
(audit/insert system
|
||||
{:name "restore-project"
|
||||
:type "action"
|
||||
:props project
|
||||
:context {:triggered-by "srepl"
|
||||
:cause "explicit call to restore-team!"}})
|
||||
|
||||
(restore-project* system project-id))))))
|
||||
|
||||
@ -652,14 +645,13 @@
|
||||
(let [team-id (h/parse-uuid team-id)
|
||||
tnow (ct/now)]
|
||||
|
||||
(audit/insert! main/system
|
||||
{::audit/name "delete-team"
|
||||
::audit/type "action"
|
||||
::audit/profile-id uuid/zero
|
||||
::audit/props {:id team-id}
|
||||
::audit/context {:triggered-by "srepl"
|
||||
:cause "explicit call to delete-profile!"}
|
||||
::audit/tracked-at tnow})
|
||||
(audit/insert main/system
|
||||
{:name "delete-team"
|
||||
:type "action"
|
||||
:props {:id team-id}
|
||||
:context {:triggered-by "srepl"
|
||||
:cause "explicit call to delete-profile!"}
|
||||
:tracked-at tnow})
|
||||
|
||||
(wrk/invoke! (-> main/system
|
||||
(assoc ::wrk/task :delete-object)
|
||||
@ -695,14 +687,12 @@
|
||||
{:id team-id}
|
||||
{::db/remove-deleted false})
|
||||
(teams/decode-row))]
|
||||
(audit/insert! system
|
||||
{::audit/name "restore-team"
|
||||
::audit/type "action"
|
||||
::audit/profile-id uuid/zero
|
||||
::audit/props team
|
||||
::audit/context {:triggered-by "srepl"
|
||||
:cause "explicit call to restore-team!"}
|
||||
::audit/tracked-at (ct/now)})
|
||||
(audit/insert system
|
||||
{:name "restore-team"
|
||||
:type "action"
|
||||
:props team
|
||||
:context {:triggered-by "srepl"
|
||||
:cause "explicit call to restore-team!"}})
|
||||
|
||||
(restore-team* system team-id))))))
|
||||
|
||||
@ -712,13 +702,12 @@
|
||||
(let [profile-id (h/parse-uuid profile-id)
|
||||
tnow (ct/now)]
|
||||
|
||||
(audit/insert! main/system
|
||||
{::audit/name "delete-profile"
|
||||
::audit/type "action"
|
||||
::audit/profile-id uuid/zero
|
||||
::audit/context {:triggered-by "srepl"
|
||||
:cause "explicit call to delete-profile!"}
|
||||
::audit/tracked-at tnow})
|
||||
(audit/insert main/system
|
||||
{:name "delete-profile"
|
||||
:type "action"
|
||||
:context {:triggered-by "srepl"
|
||||
:cause "explicit call to delete-profile!"}
|
||||
:tracked-at tnow})
|
||||
|
||||
(wrk/invoke! (-> main/system
|
||||
(assoc ::wrk/task :delete-object)
|
||||
@ -737,14 +726,12 @@
|
||||
{:id profile-id}
|
||||
{::db/remove-deleted false})
|
||||
(profile/decode-row))]
|
||||
(audit/insert! system
|
||||
{::audit/name "restore-profile"
|
||||
::audit/type "action"
|
||||
::audit/profile-id uuid/zero
|
||||
::audit/props (audit/profile->props profile)
|
||||
::audit/context {:triggered-by "srepl"
|
||||
:cause "explicit call to restore-profile!"}
|
||||
::audit/tracked-at (ct/now)})
|
||||
(audit/insert system
|
||||
{:name "restore-profile"
|
||||
:type "action"
|
||||
:props (audit/profile->props profile)
|
||||
:context {:triggered-by "srepl"
|
||||
:cause "explicit call to restore-profile!"}})
|
||||
|
||||
(db/update! system :profile
|
||||
{:deleted-at nil}
|
||||
@ -768,14 +755,14 @@
|
||||
{::db/remove-deleted false})
|
||||
(profile/decode-row))]
|
||||
(do
|
||||
(audit/insert! system
|
||||
{::audit/name "delete-profile"
|
||||
::audit/type "action"
|
||||
::audit/profile-id (:id profile)
|
||||
::audit/tracked-at deleted-at
|
||||
::audit/props (audit/profile->props profile)
|
||||
::audit/context {:triggered-by "srepl"
|
||||
:cause "explicit call to delete-profiles-in-bulk!"}})
|
||||
(audit/insert system
|
||||
{:name "delete-profile"
|
||||
:type "action"
|
||||
:profile-id (:id profile)
|
||||
:tracked-at deleted-at
|
||||
:props (audit/profile->props profile)
|
||||
:context {:triggered-by "srepl"
|
||||
:cause "explicit call to delete-profiles-in-bulk!"}})
|
||||
(wrk/invoke! (-> system
|
||||
(assoc ::wrk/task :delete-object)
|
||||
(assoc ::wrk/params {:object :profile
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user