From c7c60f6dfd3d3c9175ea1b9090915e05063bb799 Mon Sep 17 00:00:00 2001 From: LucaCappelletti94 Date: Wed, 28 Oct 2026 22:45:01 +0100 Subject: [PATCH] Drop REVOKE role FROM role with the access-control warning --- src/impls/translator_impls/statement.rs | 4 +++- tests/test_no_statement_is_silently_dropped.rs | 6 ++++++ tests/test_translation_warnings.rs | 15 +++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/impls/translator_impls/statement.rs b/src/impls/translator_impls/statement.rs index b93c77734..627193846 100644 --- a/src/impls/translator_impls/statement.rs +++ b/src/impls/translator_impls/statement.rs @@ -1952,7 +1952,9 @@ impl crate::traits::translator::TranslatorWithContext for Statement { Self::Grant(_) | Self::GrantRole(_) => { drop_with_warning("GRANT", REASON_ACCESS_CONTROL, emit) } - Self::Revoke(_) => drop_with_warning("REVOKE", REASON_ACCESS_CONTROL, emit), + Self::Revoke(_) | Self::RevokeRole(_) => { + drop_with_warning("REVOKE", REASON_ACCESS_CONTROL, emit) + } Self::Deny { .. } => drop_with_warning("DENY", REASON_ACCESS_CONTROL, emit), Self::CreateType { .. } => { drop_with_warning("CREATE TYPE", REASON_TYPE_DEFINITION, emit) diff --git a/tests/test_no_statement_is_silently_dropped.rs b/tests/test_no_statement_is_silently_dropped.rs index c4b95ceaf..edf69953d 100644 --- a/tests/test_no_statement_is_silently_dropped.rs +++ b/tests/test_no_statement_is_silently_dropped.rs @@ -80,6 +80,11 @@ const TABLE_ROLE_AND_GRANT: &str = const TWO_ROLES: &str = "CREATE TABLE t (id INTEGER PRIMARY KEY, a TEXT); CREATE ROLE r; CREATE ROLE u;"; +/// A membership `REVOKE` removes a membership `GRANT`, so that has to exist +/// too. +const TWO_ROLES_AND_MEMBERSHIP: &str = "CREATE TABLE t (id INTEGER PRIMARY KEY, a TEXT); \ + CREATE ROLE r; CREATE ROLE u; GRANT r TO u;"; + const fn emitted(sql: &'static str) -> Case { Case { setup: TABLE, sql, outcome: Outcome::Emitted } } @@ -172,6 +177,7 @@ const CASES: &[Case] = &[ outcome: Outcome::Warned, }, Case { setup: TWO_ROLES, sql: "GRANT r TO u", outcome: Outcome::Warned }, + Case { setup: TWO_ROLES_AND_MEMBERSHIP, sql: "REVOKE r FROM u", outcome: Outcome::Warned }, warned("DENY SELECT ON t TO r"), warned("DROP ROLE r"), warned("DROP USER r"), diff --git a/tests/test_translation_warnings.rs b/tests/test_translation_warnings.rs index 1a9ab4c68..2a011992f 100644 --- a/tests/test_translation_warnings.rs +++ b/tests/test_translation_warnings.rs @@ -159,6 +159,21 @@ fn revoke_emits_lossy_drop_warning() { assert_lossy_drop(&warns[2], "REVOKE"); } +#[test] +fn revoke_of_role_membership_emits_lossy_drop_warning() { + let report = Pg2Sqlite::default() + .sql("CREATE ROLE a; CREATE ROLE b; GRANT a TO b; REVOKE a FROM b;") + .expect("parse") + .translate_with_report(&Pg2SqliteOptions::default()) + .expect("translate"); + assert_eq!(report.script.iter().count(), 0, "expected no SQLite statement"); + assert_eq!(report.warnings.len(), 4); + assert_lossy_drop(&report.warnings[0], "CREATE ROLE"); + assert_lossy_drop(&report.warnings[1], "CREATE ROLE"); + assert_lossy_drop(&report.warnings[2], "GRANT"); + assert_lossy_drop(&report.warnings[3], "REVOKE"); +} + #[test] fn alter_role_emits_lossy_drop_warning() { let warns = warnings_for("CREATE ROLE alice;\nALTER ROLE alice WITH SUPERUSER;");