@@ -23,8 +23,12 @@ impl PermissionsHook {
2323 PermissionsHook { auth_manager }
2424 }
2525
26- /// Check if the current user has permission to execute a query
27- async fn check_query_permission < C > ( & self , client : & C , query : & str ) -> PgWireResult < ( ) >
26+ /// Check if the current user has permission to execute a statement
27+ async fn check_statement_permission < C > (
28+ & self ,
29+ client : & C ,
30+ statement : & Statement ,
31+ ) -> PgWireResult < ( ) >
2832 where
2933 C : ClientInfo + ?Sized ,
3034 {
@@ -35,29 +39,19 @@ impl PermissionsHook {
3539 . map ( |s| s. as_str ( ) )
3640 . unwrap_or ( "anonymous" ) ;
3741
38- // Parse query to determine required permissions
39- let query_lower = query. to_lowercase ( ) ;
40- let query_trimmed = query_lower. trim ( ) ;
41-
42- let ( required_permission, resource) = if query_trimmed. starts_with ( "select" ) {
43- ( Permission :: Select , ResourceType :: All )
44- } else if query_trimmed. starts_with ( "insert" ) {
45- ( Permission :: Insert , ResourceType :: All )
46- } else if query_trimmed. starts_with ( "update" ) {
47- ( Permission :: Update , ResourceType :: All )
48- } else if query_trimmed. starts_with ( "delete" ) {
49- ( Permission :: Delete , ResourceType :: All )
50- } else if query_trimmed. starts_with ( "create table" )
51- || query_trimmed. starts_with ( "create view" )
52- {
53- ( Permission :: Create , ResourceType :: All )
54- } else if query_trimmed. starts_with ( "drop" ) {
55- ( Permission :: Drop , ResourceType :: All )
56- } else if query_trimmed. starts_with ( "alter" ) {
57- ( Permission :: Alter , ResourceType :: All )
58- } else {
59- // For other queries (SHOW, EXPLAIN, etc.), allow all users
60- return Ok ( ( ) ) ;
42+ // Determine required permissions based on Statement type
43+ let ( required_permission, resource) = match statement {
44+ Statement :: Query ( _) => ( Permission :: Select , ResourceType :: All ) ,
45+ Statement :: Insert ( _) => ( Permission :: Insert , ResourceType :: All ) ,
46+ Statement :: Update { .. } => ( Permission :: Update , ResourceType :: All ) ,
47+ Statement :: Delete ( _) => ( Permission :: Delete , ResourceType :: All ) ,
48+ Statement :: CreateTable { .. } | Statement :: CreateView { .. } => {
49+ ( Permission :: Create , ResourceType :: All )
50+ }
51+ Statement :: Drop { .. } => ( Permission :: Drop , ResourceType :: All ) ,
52+ Statement :: AlterTable { .. } => ( Permission :: Alter , ResourceType :: All ) ,
53+ // For other statements (SET, SHOW, EXPLAIN, transactions, etc.), allow all users
54+ _ => return Ok ( ( ) ) ,
6155 } ;
6256
6357 // Check permission
@@ -78,6 +72,21 @@ impl PermissionsHook {
7872
7973 Ok ( ( ) )
8074 }
75+
76+ /// Check if a statement should skip permission checks
77+ fn should_skip_permission_check ( statement : & Statement ) -> bool {
78+ matches ! (
79+ statement,
80+ Statement :: Set { .. }
81+ | Statement :: ShowVariable { .. }
82+ | Statement :: ShowStatus { .. }
83+ | Statement :: StartTransaction { .. }
84+ | Statement :: Commit { .. }
85+ | Statement :: Rollback { .. }
86+ | Statement :: Savepoint { .. }
87+ | Statement :: ReleaseSavepoint { .. }
88+ )
89+ }
8190}
8291
8392#[ async_trait]
@@ -89,22 +98,13 @@ impl QueryHook for PermissionsHook {
8998 _session_context : & SessionContext ,
9099 client : & mut ( dyn ClientInfo + Send + Sync ) ,
91100 ) -> Option < PgWireResult < Response > > {
92- let query_lower = statement. to_string ( ) . to_lowercase ( ) ;
93-
94- // Check permissions for the query (skip for SET, transaction, and SHOW statements)
95- if !query_lower. starts_with ( "set" )
96- && !query_lower. starts_with ( "begin" )
97- && !query_lower. starts_with ( "commit" )
98- && !query_lower. starts_with ( "rollback" )
99- && !query_lower. starts_with ( "start" )
100- && !query_lower. starts_with ( "end" )
101- && !query_lower. starts_with ( "abort" )
102- && !query_lower. starts_with ( "show" )
103- {
104- let res = self . check_query_permission ( & * client, & query_lower) . await ;
105- if let Err ( e) = res {
106- return Some ( Err ( e) ) ;
107- }
101+ if Self :: should_skip_permission_check ( statement) {
102+ return None ;
103+ }
104+
105+ // Check permissions for other statements
106+ if let Err ( e) = self . check_statement_permission ( & * client, statement) . await {
107+ return Some ( Err ( e) ) ;
108108 }
109109
110110 None
@@ -127,15 +127,15 @@ impl QueryHook for PermissionsHook {
127127 _session_context : & SessionContext ,
128128 client : & mut ( dyn ClientInfo + Send + Sync ) ,
129129 ) -> Option < PgWireResult < Response > > {
130- let query = statement. to_string ( ) . to_lowercase ( ) ;
130+ if Self :: should_skip_permission_check ( statement) {
131+ return None ;
132+ }
131133
132- // Check permissions for the query (skip for SET and SHOW statements)
133- if !query. starts_with ( "set" ) && !query. starts_with ( "show" ) {
134- let res = self . check_query_permission ( & * client, & query) . await ;
135- if let Err ( e) = res {
136- return Some ( Err ( e) ) ;
137- }
134+ // Check permissions for other statements
135+ if let Err ( e) = self . check_statement_permission ( & * client, statement) . await {
136+ return Some ( Err ( e) ) ;
138137 }
138+
139139 None
140140 }
141141}
0 commit comments