| (ns ^{:added "0.51.0"} metabase.channel.models.channel
  (:require
   [malli.core :as mc]
   [metabase.models.audit-log :as audit-log]
   [metabase.models.interface :as mi]
   [metabase.models.serialization :as serdes]
   [metabase.permissions.core :as perms]
   [metabase.util :as u]
   [metabase.util.malli :as mu]
   [metabase.util.malli.registry :as mr]
   [metabase.util.malli.schema :as ms]
   [methodical.core :as methodical]
   [toucan2.core :as t2])) | |
| (set! *warn-on-reflection* true) | |
| (methodical/defmethod t2/table-name :model/Channel [_model] :channel) (methodical/defmethod t2/table-name :model/ChannelTemplate [_model] :channel_template) | |
| (doto :model/Channel (derive :metabase/model) (derive :hook/timestamped?)) | |
| (doto :model/ChannelTemplate (derive :metabase/model) (derive :hook/timestamped?)) | |
| ------------------------------------------------------------------------------------------------;; :model/Channel ;; ------------------------------------------------------------------------------------------------;; | |
| (t2/deftransforms :model/Channel
  {:type    (mi/transform-validator mi/transform-keyword (partial mi/assert-namespaced "channel"))
   :details mi/transform-encrypted-json}) | |
| (mr/def ::Channel
  "Channel schema."
  [:map
   [:name                         string?]
   [:type                         :keyword]
   [:details                      :map]
   [:active      {:optional true} :boolean]
   [:description {:optional true} [:maybe string?]]]) | |
| (defmethod mi/can-write? :model/Channel
  [& _]
  (or (mi/superuser?)
      (perms/current-user-has-application-permissions? :setting))) | |
| (t2/define-before-update :model/Channel
  [instance]
  (let [deactivation? (false? (:active (t2/changes instance)))]
    (when deactivation?
      (t2/delete! :model/PulseChannel :channel_id (:id instance)))
    (cond-> instance
      deactivation?
      ;; Channel.name has an unique constraint and it's a useful property for serialization
      ;; We rename deactivated channels so that new channels can reuse the name
      ;; Limit to 254 characters to avoid hitting character limit
      (assoc :name (u/truncate (format "DEACTIVATED_%d %s" (:id instance) (:name instance)) 254))))) | |
| (defmethod audit-log/model-details :model/Channel [channel _event-type] (select-keys channel [:id :name :description :type :active])) | |
| (defmethod serdes/entity-id "Channel" [_ {:keys [name]}] name) | |
| (defmethod serdes/hash-fields :model/Channel [_instance] [:name :type]) | |
| (defmethod serdes/make-spec "Channel"
  [_model-name _opts]
  {:copy      [:name :description :type :details :active]
   :transform {:created_at (serdes/date)}}) | |
| ------------------------------------------------------------------------------------------------;; :model/ChannelTemplate ;; ------------------------------------------------------------------------------------------------;; | |
| (t2/deftransforms :model/ChannelTemplate
  {:channel_type  (mi/transform-validator mi/transform-keyword (partial mi/assert-namespaced "channel"))
   :details       mi/transform-json}) | |
| (def ^:private channel-template-details-type
  #{:email/handlebars-text
    :email/handlebars-resource}) | |
| (mr/def ::ChannelTemplateEmailDetails
  [:merge
   [:map
    [:type                            (apply ms/enum-keywords-and-strings channel-template-details-type)]
    [:subject                         string?]
    [:recipient-type {:optional true} (ms/enum-keywords-and-strings :cc :bcc)]]
   [:multi {:dispatch (comp keyword :type)}
    [:email/handlebars-resource
     [:map
      [:path string?]]]
    [:email/handlebars-text
     [:map
      [:body string?]]]]]) | |
| (mr/def ::ChannelTemplate
  "Channel Template schema."
  [:merge
   [:map
    [:channel_type [:fn #(= "channel" (-> % keyword namespace))]]]
   [:multi {:dispatch :channel_type}
    [:channel/email
     [:map
      [:details ::ChannelTemplateEmailDetails]]]
    [::mc/default :any]]]) | |
| (defn- check-valid-channel-template [channel-template] (mu/validate-throw ::ChannelTemplate channel-template)) | |
| (t2/define-before-insert :model/ChannelTemplate [instance] (check-valid-channel-template instance) instance) | |
| (t2/define-before-update :model/ChannelTemplate [instance] (check-valid-channel-template instance) instance) | |
| (defmethod mi/can-write? :model/ChannelTemplate
  [& _]
  (or (mi/superuser?)
      (perms/current-user-has-application-permissions? :setting))) | |