diff --git a/lib/src/sql/statements/define/field.rs b/lib/src/sql/statements/define/field.rs index 65d076ae..b57660fd 100644 --- a/lib/src/sql/statements/define/field.rs +++ b/lib/src/sql/statements/define/field.rs @@ -76,15 +76,13 @@ impl Display for DefineFieldStatement { if let Some(ref v) = self.comment { write!(f, " COMMENT {v}")? } - if !self.permissions.is_full() { - let _indent = if is_pretty() { - Some(pretty_indent()) - } else { - f.write_char(' ')?; - None - }; - write!(f, "{}", self.permissions)?; - } + let _indent = if is_pretty() { + Some(pretty_indent()) + } else { + f.write_char(' ')?; + None + }; + write!(f, "{}", self.permissions)?; Ok(()) } } diff --git a/lib/src/sql/statements/define/function.rs b/lib/src/sql/statements/define/function.rs index db0bd8c1..ac4f4c0e 100644 --- a/lib/src/sql/statements/define/function.rs +++ b/lib/src/sql/statements/define/function.rs @@ -61,15 +61,13 @@ impl fmt::Display for DefineFunctionStatement { if let Some(ref v) = self.comment { write!(f, " COMMENT {v}")? } - if !self.permissions.is_full() { - let _indent = if is_pretty() { - Some(pretty_indent()) - } else { - f.write_char(' ')?; - None - }; - write!(f, "PERMISSIONS {}", self.permissions)?; - } + let _indent = if is_pretty() { + Some(pretty_indent()) + } else { + f.write_char(' ')?; + None + }; + write!(f, "PERMISSIONS {}", self.permissions)?; Ok(()) } } diff --git a/lib/src/sql/statements/define/param.rs b/lib/src/sql/statements/define/param.rs index 42ea85ac..d93fd5c4 100644 --- a/lib/src/sql/statements/define/param.rs +++ b/lib/src/sql/statements/define/param.rs @@ -50,15 +50,13 @@ impl Display for DefineParamStatement { if let Some(ref v) = self.comment { write!(f, " COMMENT {v}")? } - if !self.permissions.is_full() { - let _indent = if is_pretty() { - Some(pretty_indent()) - } else { - f.write_char(' ')?; - None - }; - write!(f, "PERMISSIONS {}", self.permissions)?; - } + let _indent = if is_pretty() { + Some(pretty_indent()) + } else { + f.write_char(' ')?; + None + }; + write!(f, "PERMISSIONS {}", self.permissions)?; Ok(()) } } diff --git a/lib/src/sql/statements/define/table.rs b/lib/src/sql/statements/define/table.rs index 7ccc4fe8..2ebdb22d 100644 --- a/lib/src/sql/statements/define/table.rs +++ b/lib/src/sql/statements/define/table.rs @@ -115,15 +115,13 @@ impl Display for DefineTableStatement { if let Some(ref v) = self.changefeed { write!(f, " {v}")?; } - if !self.permissions.is_full() { - let _indent = if is_pretty() { - Some(pretty_indent()) - } else { - f.write_char(' ')?; - None - }; - write!(f, "{}", self.permissions)?; - } + let _indent = if is_pretty() { + Some(pretty_indent()) + } else { + f.write_char(' ')?; + None + }; + write!(f, "{}", self.permissions)?; Ok(()) } } diff --git a/lib/tests/define.rs b/lib/tests/define.rs index 34e6e89e..76e06459 100644 --- a/lib/tests/define.rs +++ b/lib/tests/define.rs @@ -86,7 +86,7 @@ async fn define_statement_function() -> Result<(), Error> { "{ analyzers: {}, tokens: {}, - functions: { test: 'DEFINE FUNCTION fn::test($first: string, $last: string) { RETURN $first + $last; }' }, + functions: { test: 'DEFINE FUNCTION fn::test($first: string, $last: string) { RETURN $first + $last; } PERMISSIONS FULL' }, params: {}, scopes: {}, params: {}, @@ -509,7 +509,7 @@ async fn define_statement_field() -> Result<(), Error> { let val = Value::parse( "{ events: {}, - fields: { test: 'DEFINE FIELD test ON user' }, + fields: { test: 'DEFINE FIELD test ON user PERMISSIONS FULL' }, tables: {}, indexes: {}, lives: {}, @@ -542,7 +542,7 @@ async fn define_statement_field_type() -> Result<(), Error> { let val = Value::parse( "{ events: {}, - fields: { test: 'DEFINE FIELD test ON user TYPE string' }, + fields: { test: 'DEFINE FIELD test ON user TYPE string PERMISSIONS FULL' }, tables: {}, indexes: {}, lives: {}, @@ -575,7 +575,7 @@ async fn define_statement_field_value() -> Result<(), Error> { let val = Value::parse( r#"{ events: {}, - fields: { test: "DEFINE FIELD test ON user VALUE $value OR 'GBR'" }, + fields: { test: "DEFINE FIELD test ON user VALUE $value OR 'GBR' PERMISSIONS FULL" }, tables: {}, indexes: {}, lives: {}, @@ -608,7 +608,7 @@ async fn define_statement_field_assert() -> Result<(), Error> { let val = Value::parse( "{ events: {}, - fields: { test: 'DEFINE FIELD test ON user ASSERT $value != NONE AND $value = /[A-Z]{3}/' }, + fields: { test: 'DEFINE FIELD test ON user ASSERT $value != NONE AND $value = /[A-Z]{3}/ PERMISSIONS FULL' }, tables: {}, indexes: {}, lives: {}, @@ -641,7 +641,7 @@ async fn define_statement_field_type_value_assert() -> Result<(), Error> { let val = Value::parse( r#"{ events: {}, - fields: { test: "DEFINE FIELD test ON user TYPE string VALUE $value OR 'GBR' ASSERT $value != NONE AND $value = /[A-Z]{3}/" }, + fields: { test: "DEFINE FIELD test ON user TYPE string VALUE $value OR 'GBR' ASSERT $value != NONE AND $value = /[A-Z]{3}/ PERMISSIONS FULL" }, tables: {}, indexes: {}, lives: {}, @@ -1175,7 +1175,7 @@ async fn define_statement_analyzer() -> Result<(), Error> { }, tokens: {}, functions: { - stripHtml: "DEFINE FUNCTION fn::stripHtml($html: string) { RETURN string::replace($html, /<[^>]*>/, ''); }" + stripHtml: "DEFINE FUNCTION fn::stripHtml($html: string) { RETURN string::replace($html, /<[^>]*>/, ''); } PERMISSIONS FULL" }, params: {}, scopes: {}, @@ -1496,7 +1496,7 @@ async fn permissions_checks_define_function() { // Define the expected results for the check statement when the test statement succeeded and when it failed let check_results = [ - vec!["{ analyzers: { }, functions: { greet: \"DEFINE FUNCTION fn::greet() { RETURN 'Hello'; }\" }, params: { }, scopes: { }, tables: { }, tokens: { }, users: { } }"], + vec!["{ analyzers: { }, functions: { greet: \"DEFINE FUNCTION fn::greet() { RETURN 'Hello'; } PERMISSIONS FULL\" }, params: { }, scopes: { }, tables: { }, tokens: { }, users: { } }"], vec!["{ analyzers: { }, functions: { }, params: { }, scopes: { }, tables: { }, tokens: { }, users: { } }"] ]; @@ -1832,7 +1832,7 @@ async fn permissions_checks_define_param() { // Define the expected results for the check statement when the test statement succeeded and when it failed let check_results = [ - vec!["{ analyzers: { }, functions: { }, params: { param: \"DEFINE PARAM $param VALUE 'foo'\" }, scopes: { }, tables: { }, tokens: { }, users: { } }"], + vec!["{ analyzers: { }, functions: { }, params: { param: \"DEFINE PARAM $param VALUE 'foo' PERMISSIONS FULL\" }, scopes: { }, tables: { }, tokens: { }, users: { } }"], vec!["{ analyzers: { }, functions: { }, params: { }, scopes: { }, tables: { }, tokens: { }, users: { } }"] ]; @@ -1955,7 +1955,7 @@ async fn permissions_checks_define_field() { // Define the expected results for the check statement when the test statement succeeded and when it failed let check_results = [ - vec!["{ events: { }, fields: { field: 'DEFINE FIELD field ON TB' }, indexes: { }, lives: { }, tables: { } }"], + vec!["{ events: { }, fields: { field: 'DEFINE FIELD field ON TB PERMISSIONS FULL' }, indexes: { }, lives: { }, tables: { } }"], vec!["{ events: { }, fields: { }, indexes: { }, lives: { }, tables: { } }"] ]; @@ -2028,3 +2028,48 @@ async fn permissions_checks_define_index() { let res = iam_check_cases(test_cases.iter(), &scenario, check_results).await; assert!(res.is_ok(), "{}", res.unwrap_err()); } + +#[tokio::test] +async fn define_statement_table_permissions() -> Result<(), Error> { + // Permissions for tables, unlike other resources, are restrictive (NONE) by default. + // This test ensures that behaviour + let sql = " + DEFINE TABLE default; + DEFINE TABLE select_full PERMISSIONS FOR select FULL; + DEFINE TABLE full PERMISSIONS FULL; + INFO FOR DB; + "; + let dbs = new_ds().await?; + let ses = Session::owner().with_ns("test").with_db("test"); + let res = &mut dbs.execute(sql, &ses, None).await?; + assert_eq!(res.len(), 4); + // + let tmp = res.remove(0).result; + assert!(tmp.is_ok()); + // + let tmp = res.remove(0).result; + assert!(tmp.is_ok()); + // + let tmp = res.remove(0).result; + assert!(tmp.is_ok()); + // + let tmp = res.remove(0).result?; + let val = Value::parse( + "{ + analyzers: {}, + functions: {}, + params: {}, + scopes: {}, + tables: { + default: 'DEFINE TABLE default SCHEMALESS PERMISSIONS NONE', + full: 'DEFINE TABLE full SCHEMALESS PERMISSIONS FULL', + select_full: 'DEFINE TABLE select_full SCHEMALESS PERMISSIONS FOR select FULL, FOR create, update, delete NONE' + }, + tokens: {}, + users: {} + }", + ); + assert_eq!(tmp, val); + // + Ok(()) +} diff --git a/lib/tests/param.rs b/lib/tests/param.rs index ef408059..aa9d1bf7 100644 --- a/lib/tests/param.rs +++ b/lib/tests/param.rs @@ -29,7 +29,7 @@ async fn define_global_param() -> Result<(), Error> { analyzers: {}, tokens: {}, functions: {}, - params: { test: 'DEFINE PARAM $test VALUE 12345' }, + params: { test: 'DEFINE PARAM $test VALUE 12345 PERMISSIONS FULL' }, scopes: {}, tables: {}, users: {}, diff --git a/lib/tests/remove.rs b/lib/tests/remove.rs index fdc9de2c..1b4de2e4 100644 --- a/lib/tests/remove.rs +++ b/lib/tests/remove.rs @@ -223,7 +223,7 @@ async fn permissions_checks_remove_function() { // Define the expected results for the check statement when the test statement succeeded and when it failed let check_results = [ vec!["{ analyzers: { }, functions: { }, params: { }, scopes: { }, tables: { }, tokens: { }, users: { } }"], - vec!["{ analyzers: { }, functions: { greet: \"DEFINE FUNCTION fn::greet() { RETURN 'Hello'; }\" }, params: { }, scopes: { }, tables: { }, tokens: { }, users: { } }"], + vec!["{ analyzers: { }, functions: { greet: \"DEFINE FUNCTION fn::greet() { RETURN 'Hello'; } PERMISSIONS FULL\" }, params: { }, scopes: { }, tables: { }, tokens: { }, users: { } }"], ]; let test_cases = [ @@ -559,7 +559,7 @@ async fn permissions_checks_remove_param() { // Define the expected results for the check statement when the test statement succeeded and when it failed let check_results = [ vec!["{ analyzers: { }, functions: { }, params: { }, scopes: { }, tables: { }, tokens: { }, users: { } }"], - vec!["{ analyzers: { }, functions: { }, params: { param: \"DEFINE PARAM $param VALUE 'foo'\" }, scopes: { }, tables: { }, tokens: { }, users: { } }"], + vec!["{ analyzers: { }, functions: { }, params: { param: \"DEFINE PARAM $param VALUE 'foo' PERMISSIONS FULL\" }, scopes: { }, tables: { }, tokens: { }, users: { } }"], ]; let test_cases = [ @@ -685,7 +685,7 @@ async fn permissions_checks_remove_field() { // Define the expected results for the check statement when the test statement succeeded and when it failed let check_results = [ vec!["{ events: { }, fields: { }, indexes: { }, lives: { }, tables: { } }"], - vec!["{ events: { }, fields: { field: 'DEFINE FIELD field ON TB' }, indexes: { }, lives: { }, tables: { } }"], + vec!["{ events: { }, fields: { field: 'DEFINE FIELD field ON TB PERMISSIONS FULL' }, indexes: { }, lives: { }, tables: { } }"], ]; let test_cases = [ diff --git a/lib/tests/strict.rs b/lib/tests/strict.rs index 9e74edb3..daefd9b2 100644 --- a/lib/tests/strict.rs +++ b/lib/tests/strict.rs @@ -267,7 +267,7 @@ async fn loose_mode_all_ok() -> Result<(), Error> { let val = Value::parse( "{ events: {}, - fields: { extra: 'DEFINE FIELD extra ON test VALUE true' }, + fields: { extra: 'DEFINE FIELD extra ON test VALUE true PERMISSIONS FULL' }, tables: {}, indexes: {}, lives: {},