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)}) | |