From d4365c8af4445fd31b1f23e7186a13e1e10cab42 Mon Sep 17 00:00:00 2001
From: Noah Moss <32746338+noahmoss@users.noreply.github.com>
Date: Wed, 12 Jul 2023 08:43:33 -0400
Subject: [PATCH] make connection impersonation work when acquiring a
 connection via jdbc spec (#32238)

---
 .../advanced_permissions/driver/impersonation.clj        | 6 +++---
 .../advanced_permissions/driver/impersonation_test.clj   | 9 +++++++--
 src/metabase/driver/sql_jdbc/execute.clj                 | 5 ++---
 3 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/enterprise/backend/src/metabase_enterprise/advanced_permissions/driver/impersonation.clj b/enterprise/backend/src/metabase_enterprise/advanced_permissions/driver/impersonation.clj
index 82e762bee2f..edf086d0e1e 100644
--- a/enterprise/backend/src/metabase_enterprise/advanced_permissions/driver/impersonation.clj
+++ b/enterprise/backend/src/metabase_enterprise/advanced_permissions/driver/impersonation.clj
@@ -45,7 +45,7 @@
   Returns `nil` if connection impersonation should not be used for the current user. Throws an exception if multiple
   conflicting connection impersonation policies are found."
   [database-or-id]
-  (when-not api/*is-superuser?*
+  (when (and database-or-id (not api/*is-superuser?*))
     (let [group-ids           (t2/select-fn-set :group_id PermissionsGroupMembership :user_id api/*current-user-id*)
           conn-impersonations (enforced-impersonations
                                (when (seq group-ids)
@@ -81,8 +81,8 @@
   [driver ^Connection conn database]
   (when (driver/database-supports? driver :connection-impersonation database)
     (try
-      (let [default-role       (driver.sql/default-database-role driver database)
-            impersonation-role (connection-impersonation-role database)]
+      (let [default-role              (driver.sql/default-database-role driver database)
+            impersonation-role        (connection-impersonation-role database)]
         (driver/set-role! driver conn (or impersonation-role default-role)))
       (catch Throwable e
         (log/debug e (tru "Error setting role on connection"))
diff --git a/enterprise/backend/test/metabase_enterprise/advanced_permissions/driver/impersonation_test.clj b/enterprise/backend/test/metabase_enterprise/advanced_permissions/driver/impersonation_test.clj
index e0761563998..3064a013e9f 100644
--- a/enterprise/backend/test/metabase_enterprise/advanced_permissions/driver/impersonation_test.clj
+++ b/enterprise/backend/test/metabase_enterprise/advanced_permissions/driver/impersonation_test.clj
@@ -50,8 +50,13 @@
   (testing "Returns nil for superuser, even if they are in a group with an impersonation policy defined"
     (advanced-perms.api.tu/with-impersonations {:impersonations [{:db-id (mt/id) :attribute "impersonation_attr"}]
                                                 :attributes     {"impersonation_attr" "impersonation_role"}}
-      (is (= "impersonation_role"
-             (@#'impersonation/connection-impersonation-role (mt/db)))))))
+      (mw.session/as-admin
+       (is (nil? (@#'impersonation/connection-impersonation-role (mt/db)))))))
+
+  (testing "Does not throw an exception if passed a nil `database-or-id`"
+    (advanced-perms.api.tu/with-impersonations {:impersonations [{:db-id (mt/id) :attribute "impersonation_attr"}]
+                                                :attributes     {"impersonation_attr" "impersonation_role"}}
+      (is (nil? (@#'impersonation/connection-impersonation-role nil))))))
 
 (deftest conn-impersonation-test-postgres
   (mt/test-driver :postgres
diff --git a/src/metabase/driver/sql_jdbc/execute.clj b/src/metabase/driver/sql_jdbc/execute.clj
index 77e8487e017..634c71c06b4 100644
--- a/src/metabase/driver/sql_jdbc/execute.clj
+++ b/src/metabase/driver/sql_jdbc/execute.clj
@@ -345,9 +345,8 @@
     (log/tracef "Setting default connection options with options %s" (pr-str options))
     (set-best-transaction-level! driver conn)
     (set-time-zone-if-supported! driver conn session-timezone)
-    (set-role-if-supported! driver conn (when (u/id db-or-id-or-spec) (if (integer? db-or-id-or-spec)
-                                                                        (t2/select-one Database db-or-id-or-spec)
-                                                                        db-or-id-or-spec)))
+    (set-role-if-supported! driver conn (cond (integer? db-or-id-or-spec) (t2/select-one Database db-or-id-or-spec)
+                                              (u/id db-or-id-or-spec)     db-or-id-or-spec))
     (let [read-only? (not write?)]
       (try
         ;; Setting the connection to read-only does not prevent writes on some databases, and is meant
-- 
GitLab