-
Notifications
You must be signed in to change notification settings - Fork 1.1k
feat(AclFamily): add acl setuser command #1725
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
Conversation
// See LICENSE for licensing terms. | ||
// | ||
// | ||
|
There was a problem hiding this comment.
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 ?
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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:
template
in lambdas isC++20
and it wouldn't be wise to useauto
instead ofstd::unique_ptr<T, D>
- 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
tests/dragonfly/acl_family_test.py
Outdated
def assert_any_of(assertion, result): | ||
assert assertion == result[0] or assertion == result[1] |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
tests/dragonfly/acl_family_test.py
Outdated
|
||
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) |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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. | ||
// | ||
// | ||
|
There was a problem hiding this comment.
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?
src/server/acl/acl_family.cc
Outdated
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)); |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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 🔥
src/server/acl/acl_family.cc
Outdated
|
||
using OptCat = std::optional<uint32_t>; | ||
|
||
std::pair<OptCat, OptCat> MaybeParseAclCategory(std::string_view command) { |
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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!
src/server/acl/acl_family.cc
Outdated
maybe_update_acl(req.plus_acl_categories, acl_plus); | ||
maybe_update_acl(req.minus_acl_categories, acl_minus); |
There was a problem hiding this comment.
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)};
}
There was a problem hiding this comment.
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 🤓
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is too good 💎 💎
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍🏻
src/server/acl/acl_family.cc
Outdated
return {res->second, true}; | ||
} | ||
|
||
if (command[0] == '-' && command[1] == '@') { |
There was a problem hiding this comment.
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 😅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
StartsWith
! Fixed.
ACL SETUSER
command