Skip to content
Snippets Groups Projects
Unverified Commit 79f54d69 authored by Ngoc Khuat's avatar Ngoc Khuat Committed by GitHub
Browse files

Remove POST ee/serialization/serialize/data-model (#35849)

parent 0bc5932b
No related merge requests found
......@@ -14,7 +14,6 @@
[metabase-enterprise.content-verification.api.routes
:as content-verification]
[metabase-enterprise.sandbox.api.routes :as sandbox]
[metabase-enterprise.serialization.api.routes :as serialization]
[metabase.util.i18n :refer [deferred-tru]]))
(compojure/defroutes ^{:doc "API routes only available when running Metabase® Enterprise Edition™."} routes
......@@ -36,7 +35,4 @@
(ee.api.common/+require-premium-feature :advanced-permissions (deferred-tru "Advanced Permissions") advanced-permissions/routes))
(compojure/context
"/logs" []
(ee.api.common/+require-premium-feature :audit-app (deferred-tru "Audit app") logs/routes))
(compojure/context
"/serialization" []
(ee.api.common/+require-premium-feature :serialization (deferred-tru "Serialization") serialization/routes))))
(ee.api.common/+require-premium-feature :audit-app (deferred-tru "Audit app") logs/routes))))
(ns metabase-enterprise.serialization.api.routes
"/api/ee/serialization/ routes"
(:require
[compojure.core :as compojure]
[metabase-enterprise.serialization.api.serialize
:as
ee.api.serialization.serialize]))
;;; all these routes require the `:serialization` premium feature; this is done
;;; in [[metabase-enterprise.api.routes/routes]]
(compojure/defroutes ^{:doc "Routes for serialization endpoints."} routes
(compojure/context
"/serialize"
[]
ee.api.serialization.serialize/routes))
(ns metabase-enterprise.serialization.api.serialize
"/api/ee/serialization/serialize endpoints"
(:require
[clojure.set :as set]
[compojure.core :as compojure :refer [POST]]
[metabase-enterprise.serialization.cmd :as serialization.cmd]
[metabase.api.common :as api]
[metabase.models.collection :refer [Collection]]
[metabase.util.i18n :refer [deferred-tru tru]]
[metabase.util.malli :as mu]
[metabase.util.malli.schema :as ms]
[toucan2.core :as t2]))
(api/defendpoint POST "/data-model"
"This endpoint should serialize: the data model, settings.yaml, and all the selected Collections
The data model should only change if the user triggers a manual sync or scan (since the scheduler is turned off)
The user will need to add somewhere (probably in the admin panel):
- A path (maybe we can assume it will always dump to the same path as the Metabase jar, but we probably want to let
them define the path)
- The collections that they want to serialize (using selective serialization)"
[:as {{:keys [collection_ids path]} :body}]
{collection_ids (mu/with-api-error-message
[:fn (fn [x] (and (seq x)
(= (count x) (count (set x)))
(every? pos? x)))]
(deferred-tru "Non-empty, distinct array of Collection IDs"))
path (mu/with-api-error-message
ms/NonBlankString
(deferred-tru "Valid directory to serialize results to"))}
;; Make sure all the specified collection IDs exist.
(let [existing-collection-ids (t2/select-pks-set Collection :id [:in (set collection_ids)])]
(when-not (= (set collection_ids) (set existing-collection-ids))
(throw (ex-info (tru "Invalid Collection ID(s). These Collections do not exist: {0}"
(pr-str (set/difference (set collection_ids) (set existing-collection-ids))))
{:status-code 404}))))
(serialization.cmd/v2-dump! path {:collections collection_ids})
;; TODO -- not 100% sure this response makes sense. We can change it later with something more meaningful maybe
{:status :ok})
(api/define-routes
;; for now let's say you have to be an admin to hit any of the serialization endpoints
api/+check-superuser)
(ns metabase-enterprise.serialization.api.serialize-test
(:require
[clojure.string :as str]
[clojure.test :refer :all]
[metabase.models :refer [Card Collection Dashboard DashboardCard]]
[metabase.public-settings.premium-features-test
:as premium-features-test]
[metabase.test :as mt]
[metabase.util.files :as u.files]
[toucan2.core :as t2]))
(set! *warn-on-reflection* true)
(defn- do-serialize-data-model [f]
(premium-features-test/with-premium-features #{:serialization}
(mt/with-temp [Collection {collection-id :id
collection-eid :entity_id
collection-slug :slug} {}
Dashboard {dashboard-id :id} {:collection_id collection-id}
Card {card-id :id} {:collection_id collection-id}
DashboardCard _ {:card_id card-id :dashboard_id dashboard-id}]
(testing "Sanity Check"
(is (integer? collection-id))
(is (= collection-id
(t2/select-one-fn :collection_id Card :id card-id))))
(mt/with-temp-dir [dir "serdes-dir"]
(f {:collection-id collection-id
:collection-filename (if collection-slug
(str collection-eid "_" collection-slug)
collection-eid)
:dir dir})))))
(deftest serialize-data-model-happy-path-test
(do-serialize-data-model
(fn [{:keys [collection-id collection-filename dir]}]
(is (= {:status "ok"}
(mt/user-http-request :crowberto :post 200 "ee/serialization/serialize/data-model"
{:collection_ids [collection-id]
:path dir})))
(testing "Created files"
(letfn [(path-files [path]
(sort (map str (u.files/files-seq path))))
(files [& path-components]
(path-files (apply u.files/get-path dir path-components)))]
(is (= (map
#(.toString (u.files/get-path (System/getProperty "java.io.tmpdir") "serdes-dir" %))
["collections" "databases" "settings.yaml"])
(files)))
(testing "subdirs"
(testing "cards"
(is (= 1
(count (files "collections" collection-filename "cards")))))
(testing "collections"
(is (= 1
(->> (files "collections")
(remove #(str/ends-with? % "metabase_analytics"))
count))))
(testing "dashboards"
(is (= 1
(count (files "collections" collection-filename "dashboards")))))))))))
(deftest serialize-data-model-validation-test
(do-serialize-data-model
(fn [{:keys [collection-id dir]}]
(let [good-request {:collection_ids [collection-id]
:path dir}
serialize! (fn [& {:keys [expected-status-code
request
user]
:or {expected-status-code 400
request good-request
user :crowberto}}]
(mt/user-http-request user :post expected-status-code "ee/serialization/serialize/data-model"
request))]
(testing "Require a EE token with the `:serialization` feature"
(premium-features-test/with-premium-features #{}
(is (= "Serialization is a paid feature not currently available to your instance. Please upgrade to use it. Learn more at metabase.com/upgrade/"
(serialize! :expected-status-code 402)))))
(testing "Require current user to be a superuser"
(is (= "You don't have permissions to do that."
(serialize! :user :rasta, :expected-status-code 403))))
(testing "Require valid collection_ids"
(testing "Non-empty"
(is (=? {:errors {:collection_ids "Non-empty, distinct array of Collection IDs"}}
(serialize! :request (dissoc good-request :collection_ids))))
(is (=? {:errors {:collection_ids "Non-empty, distinct array of Collection IDs"}}
(serialize! :request (assoc good-request :collection_ids nil))))
(is (=? {:errors {:collection_ids "Non-empty, distinct array of Collection IDs"}}
(serialize! :request (assoc good-request :collection_ids [])))))
(testing "No duplicates"
(is (=? {:errors {:collection_ids "Non-empty, distinct array of Collection IDs"}}
(serialize! :request (assoc good-request :collection_ids [collection-id collection-id])))))
(testing "All Collections must exist"
(is (= (format "Invalid Collection ID(s). These Collections do not exist: #{%d}" Integer/MAX_VALUE)
(serialize! :request (assoc good-request :collection_ids [collection-id Integer/MAX_VALUE])
:expected-status-code 404))))
(testing "Invalid value"
(is (=? {:errors {:collection_ids "Non-empty, distinct array of Collection IDs"}}
(serialize! :request (assoc good-request :collection_ids collection-id))))
(is (=? {:errors {:collection_ids "Non-empty, distinct array of Collection IDs"}}
(serialize! :request (assoc good-request :collection_ids "My Collection"))))))
(testing "Validate 'path' parameter"
(is (=? {:errors {:path "Valid directory to serialize results to"}}
(serialize! :request (dissoc good-request :path))))
(is (=? {:errors {:path "Valid directory to serialize results to"}}
(serialize! :request (assoc good-request :path ""))))
(is (=? {:errors {:path "Valid directory to serialize results to"}}
(serialize! :request (assoc good-request :path 1000)))))))))
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment