diff --git a/src/metabase/api/user.clj b/src/metabase/api/user.clj index 4b3bd9a79b1853eedb78df32567e37f482f79e8e..ace9cd5ec681451e3c19bae7500b4248f72809ea 100644 --- a/src/metabase/api/user.clj +++ b/src/metabase/api/user.clj @@ -2,6 +2,7 @@ "/api/user endpoints" (:require [cemerick.friend.credentials :as creds] [compojure.core :refer [DELETE GET POST PUT]] + [honeysql.helpers :as hh] [metabase.api [common :as api] [session :as session-api]] @@ -35,10 +36,10 @@ (cond-> (db/select (vec (cons User (if api/*is-superuser?* user/admin-or-self-visible-columns user/non-admin-or-self-visible-columns))) - (merge {:order-by [[:%lower.last_name :asc] - [:%lower.first_name :asc]]} - (when-not include_deactivated - {:where [:= :is_active true]}))) + (-> {} + (hh/merge-order-by [:%lower.last_name :asc] [:%lower.first_name :asc]) + (hh/merge-where (when-not include_deactivated + [:= :is_active true])))) ;; For admins, also include the IDs of the Users' Personal Collections api/*is-superuser?* (hydrate :personal_collection_id))) diff --git a/src/metabase/models/permissions.clj b/src/metabase/models/permissions.clj index 9fc5c7438d5037d0b9bd1fc67749ba250fd4f973..ad9331b2ce24867a80e1749539eec0d4ec285c80 100644 --- a/src/metabase/models/permissions.clj +++ b/src/metabase/models/permissions.clj @@ -38,22 +38,25 @@ prevent accidental tragedy, but you can enable it here when creating the default entry for `Admin`." false) +(def segmented-perm-regex + "Regex that matches a segmented permission" + #"^/db/(\d+)/schema/([^\\/]*)/table/(\d+)/query/segmented/$") ;;; --------------------------------------------------- Validation --------------------------------------------------- (def ^:private ^:const valid-object-path-patterns - [#"^/db/(\d+)/$" ; permissions for the entire DB -- native and all schemas - #"^/db/(\d+)/native/$" ; permissions to create new native queries for the DB - #"^/db/(\d+)/schema/$" ; permissions for all schemas in the DB - #"^/db/(\d+)/schema/([^\\/]*)/$" ; permissions for a specific schema - #"^/db/(\d+)/schema/([^\\/]*)/table/(\d+)/$" ; FULL permissions for a specific table - #"^/db/(\d+)/schema/([^\\/]*)/table/(\d+)/read/$" ; Permissions to fetch the Metadata for a specific Table - #"^/db/(\d+)/schema/([^\\/]*)/table/(\d+)/query/$" ; Permissions to run any sort of query against a Table - #"^/db/(\d+)/schema/([^\\/]*)/table/(\d+)/query/segmented/$" ; Permissions to run a query against a Table using GTAP - #"^/collection/(\d+)/$" ; readwrite permissions for a collection - #"^/collection/(\d+)/read/$" ; read permissions for a collection - #"^/collection/root/$" ; readwrite permissions for the 'Root' Collection (things with `nil` collection_id) - #"^/collection/root/read/$"]) ; read permissions for the 'Root' Collection + [#"^/db/(\d+)/$" ; permissions for the entire DB -- native and all schemas + #"^/db/(\d+)/native/$" ; permissions to create new native queries for the DB + #"^/db/(\d+)/schema/$" ; permissions for all schemas in the DB + #"^/db/(\d+)/schema/([^\\/]*)/$" ; permissions for a specific schema + #"^/db/(\d+)/schema/([^\\/]*)/table/(\d+)/$" ; FULL permissions for a specific table + #"^/db/(\d+)/schema/([^\\/]*)/table/(\d+)/read/$" ; Permissions to fetch the Metadata for a specific Table + #"^/db/(\d+)/schema/([^\\/]*)/table/(\d+)/query/$" ; Permissions to run any sort of query against a Table + segmented-perm-regex ; Permissions to run a query against a Table using GTAP + #"^/collection/(\d+)/$" ; readwrite permissions for a collection + #"^/collection/(\d+)/read/$" ; read permissions for a collection + #"^/collection/root/$" ; readwrite permissions for the 'Root' Collection (things with `nil` collection_id) + #"^/collection/root/read/$"]) ; read permissions for the 'Root' Collection (defn valid-object-path? "Does OBJECT-PATH follow a known, allowed format to an *object*? diff --git a/test/metabase/api/pulse_test.clj b/test/metabase/api/pulse_test.clj index 6b1cc88edd0b39eac55371385558c59e5f60763a..cc6bb6061fd65a7c0d1470e07ef36576b459077a 100644 --- a/test/metabase/api/pulse_test.clj +++ b/test/metabase/api/pulse_test.clj @@ -917,3 +917,23 @@ ;; Don't update the pulse, but test the pulse with the updated recipients {:response ((user->client :rasta) :post 200 "pulse/test" (assoc result :channels [email-channel])) :emails (et/regex-email-bodies #"A Pulse")})))))) + +;;; +----------------------------------------------------------------------------------------------------------------+ +;;; | GET /api/pulse/form_input | +;;; +----------------------------------------------------------------------------------------------------------------+ + +;; Check that Slack channels come back when configured +(expect + [{:name "channel", :type "select", :displayName "Post to", :options ["#foo" "@bar"], :required true}] + (tu/with-temporary-setting-values [slack-token "something"] + (with-redefs [metabase.integrations.slack/channels-list (constantly [{:name "foo"}]) + metabase.integrations.slack/users-list (constantly [{:name "bar"}])] + (-> ((user->client :rasta) :get 200 "pulse/form_input") + (get-in [:channels :slack :fields]))))) + +;; When slack is not configured, `form_input` returns just the #genreal slack channel +(expect + [{:name "channel", :type "select", :displayName "Post to", :options ["#general"], :required true}] + (tu/with-temporary-setting-values [slack-token nil] + (-> ((user->client :rasta) :get 200 "pulse/form_input") + (get-in [:channels :slack :fields]))))