(ns metabase.moderation (:require [medley.core :as m] [metabase.models.interface :as mi] [metabase.util :as u] [toucan2.core :as t2])) | |
Schema enum of the acceptable values for the | (def moderated-item-types [:enum "card" :card "dashboard" :dashboard]) |
Maps DB name of the moderated item type to the model symbol (used for t2/select and such) | (def moderated-item-type->model
{"card" :model/Card
:card :model/Card
"dashboard" :model/Dashboard
:dashboard :model/Dashboard}) |
Convert a moderated item instance to the keyword stored in the database | (defn- object->type [instance] (u/lower-case-en (name (t2/model instance)))) |
(mi/define-batched-hydration-method moderation-reviews-for-items
:moderation_reviews
"Hydrate moderation reviews onto a seq of items."
[items]
;; no need to do work on empty items. Also, can have nil here due to text cards. I think this is a bug in toucan. To
;; get here we are `(t2/hydrate dashboard [:dashcards [:card :moderation_reviews] :series] ...)` But dashcards
;; dont have to have cards. but the hydration will pass the nil card id into here. NOTE: it is important that each
;; item that comes into this comes out. The nested hydration is positional, not by an id so everything that comes in
;; must go out in the same order
(when (seq items)
(let [item-ids (not-empty (keep :id items))
all-reviews (when item-ids
(group-by (juxt :moderated_item_type :moderated_item_id)
(t2/select :model/ModerationReview
:moderated_item_id [:in item-ids]
{:order-by [[:id :desc]]})))]
(for [item items]
(if (nil? item)
nil
(let [k ((juxt (comp keyword object->type) u/the-id) item)]
(assoc item :moderation_reviews (get all-reviews k ())))))))) | |
(mi/define-batched-hydration-method moderation-user-details
:moderator_details
"User details on moderation reviews"
[moderation-reviews]
(when (seq moderation-reviews)
(let [id->user (m/index-by :id
(t2/select 'User :id [:in (map :moderator_id moderation-reviews)]))]
(for [mr moderation-reviews]
(assoc mr :user (get id->user (:moderator_id mr))))))) | |
(mi/define-batched-hydration-method moderation-status
:moderation_status
"Hydrate moderation status onto a seq of items"
[items]
(when (seq items)
(let [item-ids (seq (keep :id items))
type+id->status (when item-ids
(->> (t2/select [:model/ModerationReview :moderated_item_id :moderated_item_type :status]
:moderated_item_id [:in item-ids]
:most_recent true
{:order-by [[:id :desc]]})
(group-by (juxt :moderated_item_type :moderated_item_id))
(m/map-vals #(:status (first %)))))]
(for [item items]
(some-> item
(assoc :moderation_status (get type+id->status [(keyword (object->type item))
(u/the-id item)]))))))) | |