Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MOD-8036 Add tests for 393 and 394 #395

Merged
merged 9 commits into from
Nov 4, 2024
Merged

Conversation

ephraimfeldblum
Copy link
Contributor

@ephraimfeldblum ephraimfeldblum commented Nov 3, 2024

  • Fixes the problem of naming the meta-variable class $acl_category identically to its identifier.
  • Reduces code duplication on the module side (eg RedisJSON), all commands from the module are given the ACL category of the module without having to be expressly listed per command.
    (This is not guaranteed to be correct behavior for all modules. removed).
  • Adds a test on the redismodule-rs side to ensure it works as expected.
  • Allows for a combination of optional ACL categories and mandatory ACL categories to allow for the case of optionally adding categories to commands depending on the state of the Redis Server being accessed (ie v7.2 will fail to add a new ACL category, and therefore any commands that should be linked to that category should be optional). Failing to add optional categories results in a warning. Failing to add mandatory categories is an error.

#393
#394

@eranhd
Copy link
Collaborator

eranhd commented Nov 3, 2024

please elaborate what is this PR come to fix

src/macros.rs Outdated Show resolved Hide resolved
@ephraimfeldblum
Copy link
Contributor Author

please elaborate what is this PR come to fix

  • it fixes the problem of naming the meta-variable class $acl_category identically to its identifier.
  • it reduces code duplication on the module side (eg RedisJSON), all commands from the module are given the ACL category of the module without having to be expressly listed per command.
  • it adds a test on the redismodule-rs side to ensure it works as expected.

eranhd
eranhd previously approved these changes Nov 3, 2024
eranhd
eranhd previously approved these changes Nov 3, 2024
@MeirShpilraien
Copy link
Collaborator

Please modify ACL test to verify the new functionality, and also add this option to the command proc macro (and verify it with test)

Comment on lines +10 to +12
$mandatory_acl_categories:expr
$(, $optional_acl_categories:expr)?
) => {{
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the simplicity, I'd do two things:

  1. Add a separate enum: CommandAclCategory:
enum CommandAclCategory {
    Write,
    Read,
    Fast,
    Other(String),
}

impl std::fmt::Display for CommandAclCategory {
    // ...
}

Where we would add all the already existing, commonly used acl categories which have already existed for a long time, and would always specifying a new one by having the Other variant.

  1. If the mandatory ACL category is mandatory, why not simply omit it and add it automatically? We are not in C, so we can have two macros, with it and without. In the "without" macro branch, I'd invoke the "with" branch with the mandatory ACL category name as the module name (this is the case for all the modules we are currently adding the ACLs anyway).
  2. Rename the acl_categories arguments, as we specify them separately, not all within one argument: mandatory_acl_category and optional_acl_category.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. doable. will take under advisement.
  2. there is no one singular mandatory ACL category. the mandatory ACL categories are those that are mandatory for the module to work at all, and loading the module should fail if they are not added. optional ACL categories are those that we warn on failure to add, but do not fail.
  3. we do specify multiple categories within one argument. as a space delimited string.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the response!

How we want to specify them for redis - this is the implementation detail. The interface here is in Rust, and we should allow the safest, most idiomatic way possible, which is an explicit set of type-safe values. Do you agree? For the user of this macro it shouldn't matter how exactly those end up being sent to the server, the user shouldn't care about this, nor should he know about this, if this is hidden behind the interface. This is not why this crate is simply forwarding the rust types to the C-api, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's the user that decides which categories are mandatory and which are optional, not us.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, okay, that I am not discussing anymore. I am talking now about the type safety and the explicit lists.

src/macros.rs Outdated Show resolved Hide resolved
src/macros.rs Show resolved Hide resolved
src/macros.rs Outdated Show resolved Hide resolved
@@ -146,7 +181,8 @@ macro_rules! redis_module {
$firstkey:expr,
$lastkey:expr,
$keystep:expr,
$acl_categories:expr
$mandatory_command_acl_categories:expr
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, this is plural but represents just one category; IIRC, there is just one mandatory category now, or am I wrong? Either way, I understand the precaution here of actually passing more than one as a string separated with spaces, but I'd really like to have it more verbose and explicit by having the enum and a [,] expression instead then.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there may be many mandatory categories. mandatory just means that if adding any of these categories fails, the module loading should fail.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, then I'd like to have those not as string literals but as a comma-separated values list, which implements From<T> for CommandAclCategory enum either way, so either a string, or a CommandAclCategory enum variant itself.

tests/integration.rs Outdated Show resolved Hide resolved
Copy link
Collaborator

@iddm iddm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! I don't strictly require any changes, just suggesting a few more things, but this is good to go.

impl From<&str> for AclCategory {
fn from(value: &str) -> Self {
match value {
"" => AclCategory::None,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What should the result be in the case of read or read ? Is it even possible?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

error?
passing that to Redis will be rejected

let optional_acl_categories = AclCategory::from($optional_acl_categories);
if mandatory_acl_categories != AclCategory::None && optional_acl_categories != AclCategory::None {
acl_categories = CString::new(format!("{} {}", mandatory_acl_categories, optional_acl_categories)).unwrap();
} else if optional_acl_categories != AclCategory::None {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd personally add a method for this AclCategory::is_none() and is_some(). It may clash with the interface of Option and confuse the reader, though, but there is no better alternative.

if mandatory_acl_categories != AclCategory::None && optional_acl_categories != AclCategory::None {
acl_categories = CString::new(format!("{} {}", mandatory_acl_categories, optional_acl_categories)).unwrap();
} else if optional_acl_categories != AclCategory::None {
acl_categories = CString::new(format!("{}", $optional_acl_categories)).unwrap();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we just $optional_acl_categories.to_string()?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it needs to be a c_string to pass to Redis

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know, I meant instead of using the format! macro we could have simply used the to_string() method of the fmt::Display trait, no?

@ephraimfeldblum ephraimfeldblum merged commit 670f9a4 into master Nov 4, 2024
16 checks passed
@ephraimfeldblum ephraimfeldblum deleted the ephraim_add-test-to-ACL branch November 4, 2024 14:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants