(ns metabase.request.session (:require [metabase.api.common :as api :refer [*current-user* *current-user-id* *current-user-permissions-set* *is-group-manager?* *is-superuser?*]] [metabase.models.setting :refer [*user-local-values*]] [metabase.models.user :as user] [metabase.permissions.core :as perms] [metabase.util.i18n :as i18n] [toucan2.core :as t2])) | |
(def ^:private current-user-fields (into [:model/User] user/admin-or-self-visible-columns)) | |
(defn- find-user [user-id] (when user-id (t2/select-one current-user-fields, :id user-id))) | |
User ID that we've previous bound [[user-local-values]] for. This exists so we can avoid rebinding it in recursive calls to [[with-current-user]] if it is already bound, as this can mess things up since things like [[metabase.models.setting/set-user-local-value!]] will only update the values for the top-level binding. | (def ^:private ^:dynamic *user-local-values-user-id* ;; placeholder value so we will end up rebinding [[*user-local-values*]] it if you call ;; ;; (with-current-user nil ;; ...) ;; ::none) |
Impl for [[with-current-user]]. | (defn do-with-current-user [{:keys [metabase-user-id is-superuser? permissions-set user-locale settings is-group-manager?]} thunk] (binding [*current-user-id* metabase-user-id i18n/*user-locale* user-locale *is-group-manager?* (boolean is-group-manager?) *is-superuser?* (boolean is-superuser?) *current-user* (delay (find-user metabase-user-id)) *current-user-permissions-set* (delay (or permissions-set (some-> metabase-user-id user/permissions-set))) ;; as mentioned above, do not rebind this to something new, because changes to its value will not be ;; propagated to frames further up the stack *user-local-values* (if (= *user-local-values-user-id* metabase-user-id) *user-local-values* (delay (atom (or settings (user/user-local-settings metabase-user-id))))) *user-local-values-user-id* metabase-user-id] (perms/with-relevant-permissions-for-user metabase-user-id (thunk)))) |
Part of the impl for | (defn with-current-user-fetch-user-for-id [current-user-id] (when current-user-id (t2/select-one [:model/User [:id :metabase-user-id] [:is_superuser :is-superuser?] [:locale :user-locale] :settings] :id current-user-id))) |
Execude code in body as an admin user. | (defmacro as-admin {:style/indent 0} [& body] `(do-with-current-user (merge (with-current-user-fetch-user-for-id ~`api/*current-user-id*) {:is-superuser? true :permissions-set #{"/"} :user-locale i18n/*user-locale*}) (fn [] ~@body))) |
Execute code in body with | (defmacro with-current-user {:style/indent :defn} [current-user-id & body] `(do-with-current-user (with-current-user-fetch-user-for-id ~current-user-id) (fn [] ~@body))) |