Random utilty endpoints for things that don't belong anywhere else in particular, e.g. endpoints for certain admin page tasks. | (ns metabase.api.util (:require [clj-http.client :as http] [crypto.random :as crypto-random] [environ.core :refer [env]] [metabase.analytics.core :as analytics] [metabase.api.common :as api] [metabase.api.common.validation :as validation] [metabase.api.embed.common :as api.embed.common] [metabase.api.macros :as api.macros] [metabase.config :as config] [metabase.db :as mdb] [metabase.driver :as driver] [metabase.logger :as logger] [metabase.premium-features.core :as premium-features] [metabase.util.json :as json] [metabase.util.log :as log] [metabase.util.malli :as mu] [metabase.util.malli.schema :as ms] [metabase.util.system-info :as u.system-info] [ring.util.response :as response] [toucan2.core :as t2])) |
(set! *warn-on-reflection* true) | |
(api.macros/defendpoint :post "/password_check" "Endpoint that checks if the supplied password meets the currently configured password complexity rules." [_route-params _query-params _body :- [:map [:password ms/ValidPassword]]] ;; if we pass the su/ValidPassword test we're g2g {:valid true}) | |
(api.macros/defendpoint :get "/logs" "Logs." [] (validation/check-has-application-permission :monitoring) (logger/messages)) | |
(api.macros/defendpoint :get "/stats" "Anonymous usage stats. Endpoint for testing, and eventually exposing this to instance admins to let them see what is being phoned home." [] (validation/check-has-application-permission :monitoring) (analytics/legacy-anonymous-usage-stats)) | |
(api.macros/defendpoint :get "/random_token" "Return a cryptographically secure random 32-byte token, encoded as a hexadecimal string. Intended for use when creating a value for `embedding-secret-key`." [] {:token (crypto-random/hex 32)}) | |
Product feedback url. When not prod, reads | (defn- product-feedback-url [] (if config/is-prod? "https://prod-feedback.metabase.com/api/v1/crm/product-feedback" (env :mb-product-feedback-url))) |
Sends the feedback to the api endpoint | (mu/defn send-feedback! [comments :- [:maybe ms/NonBlankString] source :- ms/NonBlankString email :- [:maybe ms/NonBlankString]] (try (http/post (product-feedback-url) {:content-type :json :body (json/encode {:comments comments :source source :email email})}) (catch Exception e (log/warn e) (throw e)))) |
(api.macros/defendpoint :post "/product-feedback" "Endpoint to provide feedback from the product" [_route-params _query-params {:keys [comments source email]} :- [:map [:comments {:optional true} [:maybe ms/NonBlankString]] [:source ms/NonBlankString] [:email {:optional true} [:maybe ms/NonBlankString]]]] (future (send-feedback! comments source email)) api/generic-204-no-content) | |
Make it easy for the user to tell us what they're using | (defn- metabase-info [] (merge {:databases (t2/select-fn-set :engine :model/Database) :run-mode (config/config-kw :mb-run-mode) :plan-alias (or (premium-features/plan-alias) "") :version config/mb-version-info :settings {:report-timezone (driver/report-timezone)} :hosting-env (analytics/environment-type) :application-database (mdb/db-type)} (when-not (premium-features/is-hosted?) {:application-database-details (t2/with-connection [^java.sql.Connection conn] (let [metadata (.getMetaData conn)] {:database {:name (.getDatabaseProductName metadata) :version (.getDatabaseProductVersion metadata)} :jdbc-driver {:name (.getDriverName metadata) :version (.getDriverVersion metadata)}}))}) (when (premium-features/airgap-enabled) {:airgap-token :enabled :max-users (premium-features/max-users-allowed) :current-user-count (premium-features/active-users-count) :valid-thru (:valid-thru (premium-features/token-status))}))) |
(api.macros/defendpoint :get "/bug_report_details" "Returns version and system information relevant to filing a bug report against Metabase." [] (validation/check-has-application-permission :monitoring) (cond-> {:metabase-info (metabase-info)} (not (premium-features/is-hosted?)) (assoc :system-info (u.system-info/system-info)))) | |
(api.macros/defendpoint :get "/diagnostic_info/connection_pool_info" "Returns database connection pool info for the current Metabase instance." [] (validation/check-has-application-permission :monitoring) (let [pool-info (analytics/connection-pool-info) headers {"Content-Disposition" "attachment; filename=\"connection_pool_info.json\""}] (assoc (response/response {:connection-pools pool-info}) :headers headers, :status 200))) | |
(api.macros/defendpoint :post "/entity_id" "Translate entity IDs to model IDs." [_route-params _query-params {:keys [entity_ids]} :- [:map [:entity_ids :map]]] {:entity_ids (api.embed.common/model->entity-ids->ids entity_ids)}) | |