(ns metabase.events.schema (:require [malli.util :as mut] [metabase.models.view-log-impl :as view-log-impl] [metabase.util.malli :as mu] [metabase.util.malli.registry :as mr] [metabase.util.malli.schema :as ms] [toucan2.core :as t2])) | |
Get the Malli schema we should use for events of | (mu/defn event-schema
[topic :- keyword?]
(or (mr/registered-schema topic)
:map)) |
Given a malli entry schema of a map, return a new entry schema with an additional option to hydrate information when sending system event notifications. (events.notification/hydrate! [:map (-> [:user_id :int] (with-hydrate :user [:model/User :email]))] {:user_id 1}) ;; => {:user_id 1 :user {:email "ngoc@metabase.com"}} | #_{:clj-kondo/ignore [:unused-private-var]}
(defn- with-hydrate
[entry-schema k model]
(assert (#{2 3} (count entry-schema)) "entry-schema must have 2 or 3 elements")
(let [[entry-key option schema] (if (= 2 (count entry-schema))
[(first entry-schema) {} (second entry-schema)]
entry-schema)]
[entry-key (assoc option :hydrate {:key k
:model model})
schema])) |
(def ^:private user-hydrate [:model/User :first_name :last_name :email]) | |
collection events | |
(mr/def :event/collection-read
[:map {:closed true}
[:user-id pos-int?]
[:object [:fn #(t2/instance-of? :model/Collection %)]]]) | |
dashboard events | |
(mr/def ::dashboard
[:map {:closed true}
[:user-id pos-int?]
[:object [:fn #(t2/instance-of? :model/Dashboard %)]]]) | |
(mr/def :event/dashboard-create ::dashboard) (mr/def :event/dashboard-update ::dashboard) (mr/def :event/dashboard-delete ::dashboard) | |
(mr/def ::dashboard-with-dashcards
(-> (event-schema ::dashboard)
(mut/assoc :dashcards [:sequential [:map [:id pos-int?]]]))) | |
(mr/def :event/dashboard-remove-cards ::dashboard-with-dashcards) (mr/def :event/dashboard-add-cards ::dashboard-with-dashcards) | |
(mr/def :event/dashboard-read
[:map {:closed true}
[:user-id [:maybe pos-int?]]
[:object-id [:maybe pos-int?]]]) | |
card events | |
(mr/def ::card
[:map {:closed true}
[:user-id [:maybe pos-int?]]
[:object [:fn #(t2/instance-of? :model/Card %)]]]) | |
(mr/def :event/card-create ::card) (mr/def :event/card-update ::card) (mr/def :event/card-delete ::card) | |
(mr/def :event/card-read
[:map {:closed true}
;; context is deliberately coupled to view-log's context
[:context view-log-impl/context]
[:user-id [:maybe pos-int?]]
[:object-id [:maybe pos-int?]]]) | |
(mr/def :event/card-query
[:map {:closed true}
[:card-id pos-int?]
[:user-id [:maybe pos-int?]]
[:context {:optional true} :any]]) | |
user events | |
(mr/def ::user
[:map {:closed true}
[:user-id pos-int?]]) | |
(mr/def :event/user-login ::user) (mr/def :event/user-joined ::user) | |
(mr/def :event/user-invited
[:map {:closed true}
[:object [:map
[:email ms/Email]
[:is_from_setup {:optional true} :boolean]
[:first_name {:optional true} [:maybe :string]]
[:invite_method {:optional true} :string]
[:sso_source {:optional true} [:maybe [:or :keyword :string]]]]]
[:details {:optional true}
[:map {:closed true}
[:invitor [:map {:closed true}
[:email ms/Email]
[:first_name {:optional true} [:maybe :string]]]]]]]) | |
metric events | |
TODO -- are these for LEGACY METRICS? ARE THESE EVENT USED ANYMORE? | |
(mr/def ::metric
[:map {:closed true}
[:user-id pos-int?]
[:object [:fn #(t2/instance-of? :model/LegacyMetric %)]]]) | |
(mr/def :event/metric-create ::metric) | |
(mr/def ::metric-with-message
[:merge
::metric
[:map {:closed true}
[:revision-message {:optional true} :string]]]) | |
(mr/def :event/metric-update ::metric-with-message) (mr/def :event/metric-delete ::metric-with-message) | |
segment events | |
(mr/def ::segment
[:map {:closed true}
[:user-id pos-int?]
[:object [:fn #(t2/instance-of? :model/Segment %)]]]) | |
(mr/def :event/segment-create ::segment) | |
(mr/def ::segment-with-message
[:merge
::segment
[:map {:closed true}
[:revision-message {:optional true} :string]]]) | |
(mr/def :event/segment-update ::segment-with-message) (mr/def :event/segment-delete ::segment-with-message) | |
database events | |
(mr/def ::database
[:map {:closed true}
[:object [:fn #(t2/instance-of? :model/Database %)]]
[:previous-object {:optional true} [:fn #(t2/instance-of? :model/Database %)]]
[:user-id pos-int?]]) | |
(mr/def :event/database-create ::database) (mr/def :event/database-update ::database) (mr/def :event/database-delete ::database) | |
alert schemas | |
(mr/def :event/alert-create
[:map {:closed true}
(-> [:user-id pos-int?]
(with-hydrate :user user-hydrate))
[:object [:and
[:fn #(t2/instance-of? :model/Pulse %)]
[:map
[:card [:fn #(t2/instance-of? :model/Card %)]]]]]]) | |
pulse schemas | |
(mr/def :event/pulse-create
[:map {:closed true}
[:user-id pos-int?]
[:object [:fn #(t2/instance-of? :model/Pulse %)]]]) | |
table events | |
(mr/def :event/table-read
[:map {:closed true}
[:user-id pos-int?]
[:object [:fn #(t2/instance-of? :model/Table %)]]]) | |
(mr/def ::permission-failure
[:map {:closed true}
[:user-id [:maybe pos-int?]]
[:object [:maybe [:fn #(boolean (t2/model %))]]]
[:has-access {:optional true} [:maybe :boolean]]]) | |
(mr/def :event/read-permission-failure ::permission-failure) (mr/def :event/write-permission-failure ::permission-failure) (mr/def :event/update-permission-failure ::permission-failure) | |
(mr/def :event/create-permission-failure
[:map {:closed true}
[:user-id [:maybe pos-int?]]
[:model [:or :keyword :string]]]) | |