vibesql_executor/
privilege_checker.rs

1use vibesql_storage::Database;
2
3use crate::errors::ExecutorError;
4
5/// Centralized privilege checking for all database operations
6pub struct PrivilegeChecker;
7
8impl PrivilegeChecker {
9    /// Check if current role has SELECT privilege on table
10    pub fn check_select(db: &Database, table_name: &str) -> Result<(), ExecutorError> {
11        Self::check_privilege(db, table_name, &vibesql_ast::PrivilegeType::Select(None), "SELECT")
12    }
13
14    /// Check if current role has INSERT privilege on table
15    pub fn check_insert(db: &Database, table_name: &str) -> Result<(), ExecutorError> {
16        Self::check_privilege(db, table_name, &vibesql_ast::PrivilegeType::Insert(None), "INSERT")
17    }
18
19    /// Check if current role has UPDATE privilege on table
20    pub fn check_update(db: &Database, table_name: &str) -> Result<(), ExecutorError> {
21        Self::check_privilege(db, table_name, &vibesql_ast::PrivilegeType::Update(None), "UPDATE")
22    }
23
24    /// Check if current role has DELETE privilege on table
25    pub fn check_delete(db: &Database, table_name: &str) -> Result<(), ExecutorError> {
26        Self::check_privilege(db, table_name, &vibesql_ast::PrivilegeType::Delete, "DELETE")
27    }
28
29    /// Check if current role has CREATE privilege (for DDL operations)
30    pub fn check_create(db: &Database, schema_name: &str) -> Result<(), ExecutorError> {
31        // For CREATE TABLE, check privilege on the schema
32        Self::check_privilege(db, schema_name, &vibesql_ast::PrivilegeType::Create, "CREATE")
33    }
34
35    /// Check if current role has DROP privilege (uses Delete privilege for DDL drops)
36    pub fn check_drop(db: &Database, object_name: &str) -> Result<(), ExecutorError> {
37        Self::check_privilege(db, object_name, &vibesql_ast::PrivilegeType::Delete, "DROP")
38    }
39
40    /// Check if current role has ALTER privilege (uses Create privilege for schema modifications)
41    pub fn check_alter(db: &Database, table_name: &str) -> Result<(), ExecutorError> {
42        // ALTER TABLE requires CREATE privilege on the table (schema modification)
43        Self::check_privilege(db, table_name, &vibesql_ast::PrivilegeType::Create, "ALTER")
44    }
45
46    /// Core privilege checking logic
47    fn check_privilege(
48        db: &Database,
49        object: &str,
50        privilege: &vibesql_ast::PrivilegeType,
51        privilege_name: &str,
52    ) -> Result<(), ExecutorError> {
53        // Skip checks if security is disabled (for testing)
54        if !db.is_security_enabled() {
55            return Ok(());
56        }
57
58        let role = db.get_current_role();
59
60        // Admin roles bypass all checks
61        if role == "ADMIN" || role == "DBA" {
62            return Ok(());
63        }
64
65        // Check if role has the required privilege
66        if db.catalog.has_privilege(&role, object, privilege) {
67            Ok(())
68        } else {
69            Err(ExecutorError::PermissionDenied {
70                role,
71                privilege: privilege_name.to_string(),
72                object: object.to_string(),
73            })
74        }
75    }
76}