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