@@ -24,12 +24,12 @@ use pgwire::types::format::FormatOptions;
2424
2525use crate :: auth:: AuthManager ;
2626use crate :: client;
27+ use crate :: hooks:: permissions:: PermissionsHook ;
2728use crate :: hooks:: set_show:: SetShowHook ;
2829use crate :: hooks:: transactions:: TransactionStatementHook ;
2930use crate :: hooks:: QueryHook ;
3031use arrow_pg:: datatypes:: df;
3132use arrow_pg:: datatypes:: { arrow_schema_to_pg_fields, into_pg_type} ;
32- use datafusion_pg_catalog:: pg_catalog:: context:: { Permission , ResourceType } ;
3333use datafusion_pg_catalog:: sql:: PostgresCompatibilityParser ;
3434
3535/// Simple startup handler that does no authentication
@@ -52,12 +52,10 @@ impl HandlerFactory {
5252
5353 pub fn new_with_hooks (
5454 session_context : Arc < SessionContext > ,
55- auth_manager : Arc < AuthManager > ,
5655 query_hooks : Vec < Arc < dyn QueryHook > > ,
5756 ) -> Self {
5857 let session_service = Arc :: new ( DfSessionService :: new_with_hooks (
5958 session_context,
60- auth_manager. clone ( ) ,
6159 query_hooks,
6260 ) ) ;
6361 HandlerFactory { session_service }
@@ -97,7 +95,6 @@ impl ErrorHandler for LoggingErrorHandler {
9795pub struct DfSessionService {
9896 session_context : Arc < SessionContext > ,
9997 parser : Arc < Parser > ,
100- auth_manager : Arc < AuthManager > ,
10198 query_hooks : Vec < Arc < dyn QueryHook > > ,
10299}
103100
@@ -106,14 +103,16 @@ impl DfSessionService {
106103 session_context : Arc < SessionContext > ,
107104 auth_manager : Arc < AuthManager > ,
108105 ) -> DfSessionService {
109- let hooks: Vec < Arc < dyn QueryHook > > =
110- vec ! [ Arc :: new( SetShowHook ) , Arc :: new( TransactionStatementHook ) ] ;
111- Self :: new_with_hooks ( session_context, auth_manager, hooks)
106+ let hooks: Vec < Arc < dyn QueryHook > > = vec ! [
107+ Arc :: new( PermissionsHook :: new( auth_manager) ) ,
108+ Arc :: new( SetShowHook ) ,
109+ Arc :: new( TransactionStatementHook ) ,
110+ ] ;
111+ Self :: new_with_hooks ( session_context, hooks)
112112 }
113113
114114 pub fn new_with_hooks (
115115 session_context : Arc < SessionContext > ,
116- auth_manager : Arc < AuthManager > ,
117116 query_hooks : Vec < Arc < dyn QueryHook > > ,
118117 ) -> DfSessionService {
119118 let parser = Arc :: new ( Parser {
@@ -124,85 +123,9 @@ impl DfSessionService {
124123 DfSessionService {
125124 session_context,
126125 parser,
127- auth_manager,
128126 query_hooks,
129127 }
130128 }
131-
132- /// Check if the current user has permission to execute a query
133- async fn check_query_permission < C > ( & self , client : & C , query : & str ) -> PgWireResult < ( ) >
134- where
135- C : ClientInfo ,
136- {
137- // Get the username from client metadata
138- let username = client
139- . metadata ( )
140- . get ( "user" )
141- . map ( |s| s. as_str ( ) )
142- . unwrap_or ( "anonymous" ) ;
143-
144- // Parse query to determine required permissions
145- let query_lower = query. to_lowercase ( ) ;
146- let query_trimmed = query_lower. trim ( ) ;
147-
148- let ( required_permission, resource) = if query_trimmed. starts_with ( "select" ) {
149- ( Permission :: Select , self . extract_table_from_query ( query) )
150- } else if query_trimmed. starts_with ( "insert" ) {
151- ( Permission :: Insert , self . extract_table_from_query ( query) )
152- } else if query_trimmed. starts_with ( "update" ) {
153- ( Permission :: Update , self . extract_table_from_query ( query) )
154- } else if query_trimmed. starts_with ( "delete" ) {
155- ( Permission :: Delete , self . extract_table_from_query ( query) )
156- } else if query_trimmed. starts_with ( "create table" )
157- || query_trimmed. starts_with ( "create view" )
158- {
159- ( Permission :: Create , ResourceType :: All )
160- } else if query_trimmed. starts_with ( "drop" ) {
161- ( Permission :: Drop , self . extract_table_from_query ( query) )
162- } else if query_trimmed. starts_with ( "alter" ) {
163- ( Permission :: Alter , self . extract_table_from_query ( query) )
164- } else {
165- // For other queries (SHOW, EXPLAIN, etc.), allow all users
166- return Ok ( ( ) ) ;
167- } ;
168-
169- // Check permission
170- let has_permission = self
171- . auth_manager
172- . check_permission ( username, required_permission, resource)
173- . await ;
174-
175- if !has_permission {
176- return Err ( PgWireError :: UserError ( Box :: new (
177- pgwire:: error:: ErrorInfo :: new (
178- "ERROR" . to_string ( ) ,
179- "42501" . to_string ( ) , // insufficient_privilege
180- format ! ( "permission denied for user \" {username}\" " ) ,
181- ) ,
182- ) ) ) ;
183- }
184-
185- Ok ( ( ) )
186- }
187-
188- /// Extract table name from query (simplified parsing)
189- fn extract_table_from_query ( & self , query : & str ) -> ResourceType {
190- let words: Vec < & str > = query. split_whitespace ( ) . collect ( ) ;
191-
192- // Simple heuristic to find table names
193- for ( i, word) in words. iter ( ) . enumerate ( ) {
194- let word_lower = word. to_lowercase ( ) ;
195- if ( word_lower == "from" || word_lower == "into" || word_lower == "table" )
196- && i + 1 < words. len ( )
197- {
198- let table_name = words[ i + 1 ] . trim_matches ( |c| c == '(' || c == ')' || c == ';' ) ;
199- return ResourceType :: Table ( table_name. to_string ( ) ) ;
200- }
201- }
202-
203- // If we can't determine the table, default to All
204- ResourceType :: All
205- }
206129}
207130
208131#[ async_trait]
@@ -230,19 +153,6 @@ impl SimpleQueryHandler for DfSessionService {
230153 let query = statement. to_string ( ) ;
231154 let query_lower = query. to_lowercase ( ) . trim ( ) . to_string ( ) ;
232155
233- // Check permissions for the query (skip for SET, transaction, and SHOW statements)
234- if !query_lower. starts_with ( "set" )
235- && !query_lower. starts_with ( "begin" )
236- && !query_lower. starts_with ( "commit" )
237- && !query_lower. starts_with ( "rollback" )
238- && !query_lower. starts_with ( "start" )
239- && !query_lower. starts_with ( "end" )
240- && !query_lower. starts_with ( "abort" )
241- && !query_lower. starts_with ( "show" )
242- {
243- self . check_query_permission ( client, & query) . await ?;
244- }
245-
246156 // Call query hooks with the parsed statement
247157 for hook in & self . query_hooks {
248158 if let Some ( result) = hook
@@ -402,12 +312,6 @@ impl ExtendedQueryHandler for DfSessionService {
402312 }
403313 }
404314
405- // Check permissions for the query (skip for SET and SHOW statements)
406- if !query. starts_with ( "set" ) && !query. starts_with ( "show" ) {
407- self . check_query_permission ( client, & portal. statement . statement . 0 )
408- . await ?;
409- }
410-
411315 if let ( _, Some ( ( _, plan) ) ) = & portal. statement . statement {
412316 let param_types = plan
413317 . get_parameter_types ( )
@@ -632,10 +536,9 @@ mod tests {
632536 // which would exit the entire statement loop, preventing subsequent statements
633537 // from being processed.
634538 let session_context = Arc :: new ( SessionContext :: new ( ) ) ;
635- let auth_manager = Arc :: new ( AuthManager :: new ( ) ) ;
636539
637540 let hooks: Vec < Arc < dyn QueryHook > > = vec ! [ Arc :: new( TestHook ) ] ;
638- let service = DfSessionService :: new_with_hooks ( session_context, auth_manager , hooks) ;
541+ let service = DfSessionService :: new_with_hooks ( session_context, hooks) ;
639542
640543 let mut client = MockClient :: new ( ) ;
641544
0 commit comments