From 32627efb96e63d85647f8bbc408536d01c16b5dc Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Sat, 9 May 2026 10:47:55 +0200 Subject: [PATCH] :construction: WIP --- backend/src/app/auth/oidc.clj | 12 +- backend/src/app/loggers/audit.clj | 355 ++++++++++-------- backend/src/app/loggers/webhooks.clj | 14 +- backend/src/app/rpc.clj | 7 +- backend/src/app/rpc/commands/audit.clj | 105 ++---- backend/src/app/rpc/commands/management.clj | 8 +- .../app/rpc/commands/teams_invitations.clj | 12 +- backend/src/app/rpc/commands/verify_token.clj | 24 +- backend/src/app/srepl/main.clj | 131 +++---- 9 files changed, 328 insertions(+), 340 deletions(-) diff --git a/backend/src/app/auth/oidc.clj b/backend/src/app/auth/oidc.clj index 3995a056e0..c6ff249e39 100644 --- a/backend/src/app/auth/oidc.clj +++ b/backend/src/app/auth/oidc.clj @@ -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))))) diff --git a/backend/src/app/loggers/audit.clj b/backend/src/app/loggers/audit.clj index 04b883b4d1..a8a862e28d 100644 --- a/backend/src/app/loggers/audit.clj +++ b/backend/src/app/loggers/audit.clj @@ -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)))) diff --git a/backend/src/app/loggers/webhooks.clj b/backend/src/app/loggers/webhooks.clj index eab1344047..2f89876e04 100644 --- a/backend/src/app/loggers/webhooks.clj +++ b/backend/src/app/loggers/webhooks.clj @@ -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)) diff --git a/backend/src/app/rpc.clj b/backend/src/app/rpc.clj index 339cc51b14..0edbc49b4c 100644 --- a/backend/src/app/rpc.clj +++ b/backend/src/app/rpc.clj @@ -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)) diff --git a/backend/src/app/rpc/commands/audit.clj b/backend/src/app/rpc/commands/audit.clj index dc2b7a3c1a..350c3ed5b0 100644 --- a/backend/src/app/rpc/commands/audit.clj +++ b/backend/src/app/rpc/commands/audit.clj @@ -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 diff --git a/backend/src/app/rpc/commands/management.clj b/backend/src/app/rpc/commands/management.clj index 0908b358d7..974004ec63 100644 --- a/backend/src/app/rpc/commands/management.clj +++ b/backend/src/app/rpc/commands/management.clj @@ -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)) diff --git a/backend/src/app/rpc/commands/teams_invitations.clj b/backend/src/app/rpc/commands/teams_invitations.clj index dfc83000a5..9d59b63b88 100644 --- a/backend/src/app/rpc/commands/teams_invitations.clj +++ b/backend/src/app/rpc/commands/teams_invitations.clj @@ -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) diff --git a/backend/src/app/rpc/commands/verify_token.clj b/backend/src/app/rpc/commands/verify_token.clj index 38a3e2b42f..246c35fe11 100644 --- a/backend/src/app/rpc/commands/verify_token.clj +++ b/backend/src/app/rpc/commands/verify_token.clj @@ -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)) diff --git a/backend/src/app/srepl/main.clj b/backend/src/app/srepl/main.clj index 30c8b403dc..10132575f1 100644 --- a/backend/src/app/srepl/main.clj +++ b/backend/src/app/srepl/main.clj @@ -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