Skip to content
Snippets Groups Projects
Unverified Commit 3ced541f authored by Oleksandr Yakushev's avatar Oleksandr Yakushev Committed by GitHub
Browse files

perf: Use vectors to iterate over all user permissions (#48025)

parent 2173e659
No related branches found
No related tags found
No related merge requests found
......@@ -182,6 +182,7 @@
[metabase.util.log :as log]
[metabase.util.malli :as mu]
[metabase.util.malli.schema :as ms]
[metabase.util.performance :as perf]
[methodical.core :as methodical]
[toucan2.core :as t2]))
......@@ -277,25 +278,27 @@
(defn set-has-full-permissions?
"Does `permissions-set` grant *full* access to object with `path`?"
^Boolean [permissions-set path]
(boolean (some #(is-permissions-for-object? % path) permissions-set)))
(boolean (perf/some #(is-permissions-for-object? % path) permissions-set)))
(defn set-has-partial-permissions?
"Does `permissions-set` grant access full access to object with `path` *or* to a descendant of it?"
^Boolean [permissions-set path]
(boolean (some #(is-partial-permissions-for-object? % path) permissions-set)))
(boolean (perf/some #(is-partial-permissions-for-object? % path) permissions-set)))
(mu/defn set-has-full-permissions-for-set? :- :boolean
"Do the permissions paths in `permissions-set` grant *full* access to all the object paths in `paths-set`?"
[permissions-set paths-set]
(every? (partial set-has-full-permissions? permissions-set)
paths-set))
(let [permissions (or (:as-vec (meta permissions-set))
permissions-set)]
(every? (partial set-has-full-permissions? permissions) paths-set)))
(mu/defn set-has-partial-permissions-for-set? :- :boolean
"Do the permissions paths in `permissions-set` grant *partial* access to all the object paths in `paths-set`?
(`permissions-set` must grant partial access to *every* object in `paths-set` set)."
[permissions-set paths-set]
(every? (partial set-has-partial-permissions? permissions-set)
paths-set))
(let [permissions (or (:as-vec (meta permissions-set))
permissions-set)]
(every? (partial set-has-partial-permissions? permissions) paths-set)))
(mu/defn set-has-application-permission-of-type? :- :boolean
"Does `permissions-set` grant *full* access to a application permission of type `perm-type`?"
......
......@@ -250,16 +250,19 @@
(defn permissions-set
"Return a set of all permissions object paths that `user-or-id` has been granted access to. (2 DB Calls)"
[user-or-id]
(set (when-let [user-id (u/the-id user-or-id)]
(concat
;; Current User always gets readwrite perms for their Personal Collection and for its descendants! (1 DB Call)
(map perms/collection-readwrite-path (collection/user->personal-collection-and-descendant-ids user-or-id))
;; include the other Perms entries for any Group this User is in (1 DB Call)
(map :object (mdb.query/query {:select [:p.object]
:from [[:permissions_group_membership :pgm]]
:join [[:permissions_group :pg] [:= :pgm.group_id :pg.id]
[:permissions :p] [:= :p.group_id :pg.id]]
:where [:= :pgm.user_id user-id]}))))))
(let [s
(set (when-let [user-id (u/the-id user-or-id)]
(concat
;; Current User always gets readwrite perms for their Personal Collection and for its descendants! (1 DB Call)
(map perms/collection-readwrite-path (collection/user->personal-collection-and-descendant-ids user-or-id))
;; include the other Perms entries for any Group this User is in (1 DB Call)
(map :object (mdb.query/query {:select [:p.object]
:from [[:permissions_group_membership :pgm]]
:join [[:permissions_group :pg] [:= :pgm.group_id :pg.id]
[:permissions :p] [:= :p.group_id :pg.id]]
:where [:= :pgm.user_id user-id]})))))]
;; Append permissions as a vector for more efficient iteration in checks that go over each permission linearly.
(with-meta s {:as-vec (vec s)})))
;;; --------------------------------------------------- Hydration ----------------------------------------------------
......
(ns metabase.util.performance
"Functions and utilities for faster processing."
(:refer-clojure :exclude [reduce mapv])
(:refer-clojure :exclude [reduce mapv some])
(:import (clojure.lang LazilyPersistentVector RT)))
(set! *warn-on-reflection* true)
......@@ -126,3 +126,8 @@
([x y] (mapv #(% x y) fns))
([x y z] (mapv #(% x y z) fns))
([x y z & args] (mapv #(apply % x y z args) fns)))))
(defn some
"Like `clojure.core/some` but uses our custom `reduce` which in turn uses iterators."
[f coll]
(unreduced (reduce #(when-let [match (f %2)] (reduced match)) nil coll)))
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