Skip to content

Conversation

kostasrim
Copy link
Contributor

  • Add ACL SETUSER command
  • Add tests

@kostasrim kostasrim marked this pull request as ready for review August 23, 2023 05:55
// See LICENSE for licensing terms.
//
//

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We have this but the implementation is slightly different because it adds an extra overloads.
Also I am not sure if we can have the licence here ?

Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe you can also replace the overloaded in other files wit this include?

Copy link
Contributor Author

@kostasrim kostasrim Aug 23, 2023

Choose a reason for hiding this comment

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

It's only used in dragonfly_connection.cc

template <class... Ts> struct Overloaded : Ts... {
    using Ts::operator()...;
   
    template <typename T, typename D> size_t operator()(const unique_ptr<T, D>& ptr) {
        return operator()(*ptr.get());
    }
 };

So I can't really replace it because:

  1. template in lambdas is C++20 and it wouldn't be wise to use auto instead of std::unique_ptr<T, D>
  2. I could inherit from my Overload but that would be exactly of the same verbosity + we would need a new deduction rule for this new derived class (therefore literally exactly the same code)

There are some things in C++20 I really love and would be useful in certain cases -- who knows maybe we consider it at some point in the future :D

@kostasrim kostasrim self-assigned this Aug 23, 2023
@kostasrim kostasrim requested review from dranikpg and romange August 23, 2023 05:55
Comment on lines 17 to 18
def assert_any_of(assertion, result):
assert assertion == result[0] or assertion == result[1]
Copy link
Contributor

Choose a reason for hiding this comment

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

small nit: better have the function return bool and assert its condition so you can see the failed line

Copy link
Contributor Author

@kostasrim kostasrim Aug 23, 2023

Choose a reason for hiding this comment

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

This is not a small nit but essential. I was very dissatisfied that it would not print the line and I wanted to comment on that. Thankfully you did first + I think your other comment using in is far more better so I opted in for that


await async_client.execute_command("ACL SETUSER kostas -@list -@admin")
result = await async_client.execute_command("ACL LIST")
assert_any_of("user kostas on nopass +@STRING", result)
Copy link
Contributor

Choose a reason for hiding this comment

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

actually, instead of the function you can do assert "user kostas..." in result

Copy link
Contributor Author

Choose a reason for hiding this comment

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

🤯

// See LICENSE for licensing terms.
//
//

Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe you can also replace the overloaded in other files wit this include?

Comment on lines 155 to 161
auto error_case = [cntx](std::string&& error) { (*cntx)->SendError(error); };
auto update_case = [username, cntx](User::UpdateRequest&& req) {
ServerState::tlocal()->user_registry->MaybeAddAndUpdate(username, std::move(req));
(*cntx)->SendOk();
};

std::visit(Overloaded{error_case, update_case}, std::move(req));
Copy link
Contributor

Choose a reason for hiding this comment

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

Its unusual to see it being done this way though I like this direction more than how we generally do it

Often we just use a function like optional<Result> ParseXXXOrReply(). It seems ok for me because those functions are unlikely to be ever re-used in a modular way where replies are not desirable.

Small nit: We now have a ErrorReply type that can be used instead of a 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 seems ok for me because those functions are unlikely to be ever re-used in a modular way where replies are not desirable.

100% they are local to the scope

Small nit: We now have a ErrorReply type that can be used instead of a string

Lit lit lit 🔥


using OptCat = std::optional<uint32_t>;

std::pair<OptCat, OptCat> MaybeParseAclCategory(std::string_view command) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I would note somewhere that the first are added cats and the second removed cats (though can be inferred from the +/- signs below)

Copy link
Contributor

Choose a reason for hiding this comment

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

Actually, don't you think that returning a Cat + bool (add) would be much shorter and easier than working with the pair?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's a very good suggestion -- I like this!

Comment on lines 143 to 144
maybe_update_acl(req.plus_acl_categories, acl_plus);
maybe_update_acl(req.minus_acl_categories, acl_minus);
Copy link
Contributor

Choose a reason for hiding this comment

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

🤯 🔫

So if you choose to use the optional<[cat, bool remove]> you can just

if (result) {
  auto* acl_field = result.second ? &req.minus_acl_categories : req.plus_acl_categories;
  *acl_field |=  result.first;
} else {
  return ErrorReply{absl::StrCat("Unrecognized paramter", command)};
}

Copy link
Contributor

Choose a reason for hiding this comment

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

If acl_field is an optional you can do *acl_field = acl_field -> value_or(0) | result.first instead of adding if's 🤓

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is too good 💎 💎

@kostasrim kostasrim requested a review from dranikpg August 23, 2023 15:28
dranikpg
dranikpg previously approved these changes Aug 23, 2023
Copy link
Contributor

@dranikpg dranikpg left a comment

Choose a reason for hiding this comment

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

👍🏻

return {res->second, true};
}

if (command[0] == '-' && command[1] == '@') {
Copy link
Contributor

@dranikpg dranikpg Aug 23, 2023

Choose a reason for hiding this comment

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

You can really squash it into a single if statement 😅

Copy link
Contributor Author

Choose a reason for hiding this comment

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

StartsWith! Fixed.

@kostasrim kostasrim enabled auto-merge (squash) August 24, 2023 08:40
@kostasrim kostasrim merged commit bd87fb7 into main Aug 24, 2023
@kostasrim kostasrim deleted the acl_part_4_add_acl_set_user branch August 24, 2023 10:24
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.

2 participants