Newer
Older
(ns metabase-enterprise.advanced-permissions.common
(:require
[metabase.api.common :as api]
[metabase.models :refer [PermissionsGroupMembership]]
[metabase.models.data-permissions :as data-perms]
[metabase.models.database :as database]
[metabase.models.permissions :as perms]
[metabase.models.permissions-group :as perms-group]
[metabase.public-settings.premium-features
:as premium-features
:refer [defenterprise]]
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
(defenterprise current-user-can-write-field?
"Enterprise version. Returns a boolean whether the current user can write the given field."
:feature :advanced-permissions
[instance]
(let [db-id (or (get-in instance [:table :db_id])
(database/table-id->database-id (:table_id instance)))]
(data-perms/user-has-permission-for-table?
api/*current-user-id*
:perms/manage-table-metadata
:yes
db-id
(:table_id instance))))
(defenterprise current-user-can-read-schema?
"Enterprise version. Returns a boolean whether the current user can read the given schema"
:feature :advanced-permissions
[db-id schema-name]
(data-perms/user-has-permission-for-schema?
api/*current-user-id*
:perms/manage-table-metadata
:yes
db-id
schema-name))
(defenterprise current-user-can-write-db?
"Enterprise version. Returns a boolean whether the current user can write the given db"
:feature :advanced-permissions
[db-id]
(data-perms/user-has-permission-for-database?
api/*current-user-id*
:perms/manage-database
:yes
db-id))
(defenterprise current-user-can-write-table?
"Enterprise version."
:feature :advanced-permissions
[table]
(data-perms/user-has-permission-for-table?
api/*current-user-id*
:perms/manage-table-metadata
:yes
(:db_id table)
(:id table)))
(defn with-advanced-permissions
"Adds to `user` a set of boolean flag indiciate whether or not current user has access to an advanced permissions.
This function is meant to be used for GET /api/user/current "
[user]
(let [permissions-set @api/*current-user-permissions-set*]
(assoc user :permissions
{:can_access_setting (perms/set-has-application-permission-of-type? permissions-set :setting)
:can_access_subscription (perms/set-has-application-permission-of-type? permissions-set :subscription)
:can_access_monitoring (perms/set-has-application-permission-of-type? permissions-set :monitoring)
:can_access_data_model (data-perms/user-has-any-perms-of-type? api/*current-user-id* :perms/manage-table-metadata)
:can_access_db_details (data-perms/user-has-any-perms-of-type? api/*current-user-id* :perms/manage-database)
:is_group_manager api/*is-group-manager?*})))
(defn current-user-has-application-permissions?
"Check if `*current-user*` has permissions for a application permissions of type `perm-type`."
[perm-type]
(or api/*is-superuser?*
(perms/set-has-application-permission-of-type? @api/*current-user-permissions-set* perm-type)))
(defn current-user-is-manager-of-group?
"Return true if current-user is a manager of `group-or-id`."
[group-or-id]
(t2/select-one-fn :is_group_manager PermissionsGroupMembership
:user_id api/*current-user-id* :group_id (u/the-id group-or-id)))
(defn filter-tables-by-data-model-perms
"Given a list of tables, removes the ones for which `*current-user*` does not have data model editing permissions."
(cond
api/*is-superuser?*
;; If advanced-permissions is not enabled, no non-admins have any data-model editing perms, so return an empty list
(not (premium-features/enable-advanced-permissions?))
(empty tables)
:else
(fn [{table-id :id db-id :db_id}]
(data-perms/user-has-permission-for-table?
api/*current-user-id*
:perms/manage-table-metadata
:yes
db-id
table-id))
Noah Moss
committed
Alexander Polyankin
committed
(defn filter-schema-by-data-model-perms
"Given a list of schema, remove the ones for which `*current-user*` does not have data model editing permissions."
[schema]
(cond
api/*is-superuser?*
schema
;; If advanced-permissions is not enabled, no non-admins have any data-model editing perms, so return an empty list
(not (premium-features/enable-advanced-permissions?))
(empty schema)
:else
(filter
(fn [{db-id :db_id schema :schema}]
(data-perms/user-has-permission-for-schema?
api/*current-user-id*
:perms/manage-table-metadata
:yes
db-id
schema))
Alexander Polyankin
committed
schema)))
Noah Moss
committed
(defn filter-databases-by-data-model-perms
"Given a list of databases, removes the ones for which `*current-user*` has no data model editing permissions.
If databases are already hydrated with their tables, also removes tables for which `*current-user*` has no data
model editing perms."
Noah Moss
committed
[dbs]
(cond
api/*is-superuser?*
Noah Moss
committed
dbs
;; If advanced-permissions is not enabled, no non-admins have any data-model editing perms, so return an empty list
(not (premium-features/enable-advanced-permissions?))
(empty dbs)
:else
Noah Moss
committed
(reduce
(fn [result {db-id :id tables :tables :as db}]
(if (= (data-perms/most-permissive-database-permission-for-user api/*current-user-id* :perms/manage-table-metadata db-id)
:yes)
Noah Moss
committed
(if tables
(conj result (update db :tables filter-tables-by-data-model-perms))
(conj result db))
Noah Moss
committed
[]
dbs)))
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
(defenterprise new-database-view-data-permission-level
"Returns the default view-data permission level for a new database for a given group. This is `blocked` if the
group has block permissions for any existing database, or if any connection impersonation policies or sandboxes
exist. Otherwise, it is `unrestricted`."
;; We use :feature :none here since sandboxing uses a different feature flag from block perms & connection
;; impersonation, so we need to check the flags in the function body.
:feature :none
[group-id]
(if (or
(and
(premium-features/enable-advanced-permissions?)
(t2/exists? :model/DataPermissions
:perm_type :perms/view-data
:perm_value :blocked
:group_id group-id))
(and
(premium-features/enable-advanced-permissions?)
(t2/exists? :model/ConnectionImpersonation
:group_id group-id))
(and
(premium-features/enable-sandboxes?)
(t2/exists? :model/GroupTableAccessPolicy
:group_id group-id)))
:blocked
:unrestricted))
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
(defenterprise new-group-view-data-permission-level
"Returns the default view-data permission level for a new group for a given database. This is `blocked` if All Users
has block permissions for the database, or if any connection impersonation policies or sandboxes exist. Otherwise, it
is `unrestricted`."
:feature :none
[db-id]
(let [all-users-group-id (u/the-id (perms-group/all-users))]
(if (or
(and
(premium-features/enable-advanced-permissions?)
(t2/exists? :model/DataPermissions
:perm_type :perms/view-data
:perm_value :blocked
:db_id db-id
:group_id all-users-group-id))
(and
(premium-features/enable-advanced-permissions?)
(t2/exists? :model/ConnectionImpersonation
:group_id all-users-group-id
:db_id db-id))
(and
(premium-features/enable-sandboxes?)
(t2/exists? :model/GroupTableAccessPolicy
:group_id all-users-group-id
{:from [[:sandboxes :s]]
:join [[:metabase_table :t] [:= :s.table_id :t.id]]
:where [:= :t.db_id db-id]})))
:blocked
:unrestricted)))