Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Write path for download permission graphs (#20759)
- Loading branch information
Showing
5 changed files
with
338 additions
and
25 deletions.
There are no files selected for viewing
105 changes: 105 additions & 0 deletions
105
enterprise/backend/src/metabase_enterprise/advanced_permissions/models/permissions.clj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
(ns metabase-enterprise.advanced-permissions.models.permissions | ||
(:require [metabase.models.permissions :as perms] | ||
[metabase.util.schema :as su] | ||
[schema.core :as s])) | ||
|
||
;;; +----------------------------------------------------------------------------------------------------------------+ | ||
;;; | Shared Util Functions | | ||
;;; +----------------------------------------------------------------------------------------------------------------+ | ||
|
||
(defn- all-schemas-path | ||
[perm-type perm-value db-id] | ||
(perms/base->feature-perms-path perm-type perm-value (perms/all-schemas-path db-id))) | ||
|
||
(defn- grant-permissions-for-all-schemas! | ||
[perm-type perm-value group-id db-id] | ||
(perms/grant-permissions! group-id (all-schemas-path perm-type perm-value db-id))) | ||
|
||
(defn- revoke-permissions! | ||
{:arglists '([perm-type perm-value group-id db-id] | ||
[perm-type perm-value group-id db-id schema-name] | ||
[perm-type perm-value group-id db-id schema-name table-or-id])} | ||
[perm-type perm-value group-id & path-components] | ||
(perms/delete-related-permissions! group-id | ||
(apply (partial perms/feature-perms-path perm-type perm-value) path-components))) | ||
|
||
|
||
;;; +----------------------------------------------------------------------------------------------------------------+ | ||
;;; | Download permissions | | ||
;;; +----------------------------------------------------------------------------------------------------------------+ | ||
|
||
(defn- revoke-download-permissions! | ||
{:arglists '([group-id db-id] | ||
[group-id db-id schema-name] | ||
[group-id db-id schema-name table-or-id])} | ||
[group-id & path-components] | ||
(apply (partial revoke-permissions! :download :full group-id) path-components) | ||
(apply (partial revoke-permissions! :download :limited group-id) path-components)) | ||
|
||
(defn- update-table-download-permissions! | ||
[group-id db-id schema table-id new-table-perms] | ||
(condp = new-table-perms | ||
:full | ||
(do | ||
(revoke-download-permissions! group-id db-id schema table-id) | ||
(perms/grant-permissions! group-id (perms/feature-perms-path :download :full db-id schema table-id))) | ||
|
||
:limited | ||
(do | ||
(revoke-download-permissions! group-id db-id schema table-id) | ||
(perms/grant-permissions! group-id (perms/feature-perms-path :download :limited db-id schema table-id))) | ||
|
||
:none | ||
(revoke-download-permissions! group-id db-id schema table-id))) | ||
|
||
(defn- update-schema-download-permissions! | ||
[group-id db-id schema new-schema-perms] | ||
(condp = new-schema-perms | ||
:full | ||
(do | ||
(revoke-download-permissions! group-id db-id schema) | ||
(perms/grant-permissions! group-id (perms/feature-perms-path :download :full db-id schema))) | ||
|
||
:limited | ||
(do | ||
(revoke-download-permissions! group-id db-id schema) | ||
(perms/grant-permissions! group-id (perms/feature-perms-path :download :limited db-id schema))) | ||
|
||
:none | ||
(revoke-download-permissions! group-id db-id schema) | ||
|
||
(when (map? new-schema-perms) | ||
(doseq [[table-id table-perms] new-schema-perms] | ||
(update-table-download-permissions! group-id db-id schema table-id table-perms))))) | ||
|
||
(s/defn update-db-download-permissions! | ||
"Update the download permissions graph for a database. | ||
This mostly works similar to [[metabase.models.permission/update-db-data-access-permissions!]], with a few key | ||
differences: | ||
- Permissions have three levels: full, limited, and none. | ||
- Native query download permissions are fully inferred from the non-native download permissions. For more details, | ||
see the docstring for [[metabase.models.permissions/update-native-download-permissions!]]." | ||
[group-id :- su/IntGreaterThanZero db-id :- su/IntGreaterThanZero new-download-perms :- perms/DownloadPermissionsGraph] | ||
(when-let [schemas (:schemas new-download-perms)] | ||
(condp = schemas | ||
:full | ||
(do | ||
(revoke-download-permissions! group-id db-id) | ||
(grant-permissions-for-all-schemas! :download :full group-id db-id)) | ||
|
||
:limited | ||
(do | ||
(revoke-download-permissions! group-id db-id) | ||
(grant-permissions-for-all-schemas! :download :limited group-id db-id)) | ||
|
||
:none | ||
(revoke-download-permissions! group-id db-id) | ||
|
||
(when (map? schemas) | ||
(doseq [[schema new-schema-perms] (seq schemas)] | ||
(update-schema-download-permissions! group-id db-id schema new-schema-perms))))) | ||
;; We need to call update-native-download-permissions! whenever any download permissions are changed, but after we've | ||
;; updated non-native donwload permissions. This is because native download permissions are fully computed from the | ||
;; non-native download permissions. | ||
(perms/update-native-download-permissions! group-id db-id)) |
78 changes: 78 additions & 0 deletions
78
enterprise/backend/test/metabase_enterprise/advanced_permissions/models/permissions_test.clj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
(ns metabase-enterprise.advanced-permissions.models.permissions-test | ||
(:require [clojure.test :refer :all] | ||
[metabase-enterprise.advanced-permissions.models.permissions :as ee-perms] | ||
[metabase.models :refer [Permissions PermissionsGroup]] | ||
[metabase.models.database :as database] | ||
[metabase.models.permissions :as perms] | ||
[metabase.public-settings.premium-features-test :as premium-features-test] | ||
[metabase.test :as mt] | ||
[metabase.util :as u])) | ||
|
||
(defn- download-perms-by-group-id [group-id] | ||
(get-in (perms/data-perms-graph) [:groups group-id (mt/id) :download])) | ||
|
||
(deftest update-db-download-permissions-test | ||
(premium-features-test/with-premium-features #{:advanced-permissions} | ||
(mt/with-model-cleanup [Permissions] | ||
(mt/with-temp PermissionsGroup [{group-id :id}] | ||
(testing "Download perms for all schemas can be set and revoked" | ||
(ee-perms/update-db-download-permissions! group-id (mt/id) {:schemas :full}) | ||
(is (= {:schemas :full, :native :full} | ||
(download-perms-by-group-id group-id))) | ||
|
||
(ee-perms/update-db-download-permissions! group-id (mt/id) {:schemas :limited}) | ||
(is (= {:schemas :limited, :native :limited} | ||
(download-perms-by-group-id group-id))) | ||
|
||
(ee-perms/update-db-download-permissions! group-id (mt/id) {:schemas :none}) | ||
(is (nil? (download-perms-by-group-id group-id)))) | ||
|
||
(testing "Download perms for individual schemas can be set and revoked" | ||
(ee-perms/update-db-download-permissions! group-id (mt/id) {:schemas {"PUBLIC" :full}}) | ||
(is (= {:schemas {"PUBLIC" :full} :native :full} | ||
(download-perms-by-group-id group-id))) | ||
|
||
(ee-perms/update-db-download-permissions! group-id (mt/id) {:schemas {"PUBLIC" :limited}}) | ||
(is (= {:schemas {"PUBLIC" :limited} :native :limited} | ||
(download-perms-by-group-id group-id))) | ||
|
||
(ee-perms/update-db-download-permissions! group-id (mt/id) {:schemas {"PUBLIC" :none}}) | ||
(is (nil? (download-perms-by-group-id group-id)))) | ||
|
||
(testing "Download perms for individual tables can be set and revoked" | ||
(let [[id-1 id-2 id-3 id-4] (map u/the-id (database/tables (mt/db)))] | ||
(ee-perms/update-db-download-permissions! group-id (mt/id) {:schemas {"PUBLIC" {id-1 :full | ||
id-2 :full | ||
id-3 :full | ||
id-4 :full}}}) | ||
(is (= {:schemas {"PUBLIC" {id-1 :full id-2 :full id-3 :full id-4 :full}} | ||
:native :full} | ||
(download-perms-by-group-id group-id))) | ||
|
||
(ee-perms/update-db-download-permissions! group-id (mt/id) {:schemas {"PUBLIC" {id-1 :limited}}}) | ||
(is (= {:schemas {"PUBLIC" {id-1 :limited id-2 :full id-3 :full id-4 :full}} | ||
:native :limited} | ||
(download-perms-by-group-id group-id))) | ||
|
||
(ee-perms/update-db-download-permissions! group-id (mt/id) {:schemas {"PUBLIC" {id-2 :none}}}) | ||
(is (= {:schemas {"PUBLIC" {id-1 :limited id-3 :full id-4 :full}}} | ||
(download-perms-by-group-id group-id))) | ||
|
||
(ee-perms/update-db-download-permissions! group-id (mt/id) {:schemas {"PUBLIC" {id-1 :none | ||
id-3 :none | ||
id-4 :none}}}) | ||
(is (nil? (download-perms-by-group-id group-id))) | ||
|
||
(ee-perms/update-db-download-permissions! group-id (mt/id) {:schemas {"PUBLIC" {id-1 :full | ||
id-2 :full | ||
id-3 :limited | ||
id-4 :limited}}}) | ||
(is (= {:schemas {"PUBLIC" {id-1 :full id-2 :full id-3 :limited id-4 :limited}} | ||
:native :limited} | ||
(download-perms-by-group-id group-id))) | ||
|
||
(ee-perms/update-db-download-permissions! group-id (mt/id) {:schemas {"PUBLIC" {id-3 :full | ||
id-4 :full}}}) | ||
(is (= {:schemas {"PUBLIC" {id-1 :full id-2 :full id-3 :full id-4 :full}} | ||
:native :full} | ||
(download-perms-by-group-id group-id))))))))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.