3
3
4
4
#include " server/acl/acl_family.h"
5
5
6
+ #include < glog/logging.h>
7
+
6
8
#include < cctype>
7
9
#include < optional>
8
10
#include < variant>
12
14
#include " absl/strings/match.h"
13
15
#include " absl/strings/str_cat.h"
14
16
#include " core/overloaded.h"
17
+ #include " facade/dragonfly_connection.h"
15
18
#include " facade/facade_types.h"
16
19
#include " server/acl/acl_commands_def.h"
17
20
#include " server/command_registry.h"
@@ -157,12 +160,31 @@ std::variant<User::UpdateRequest, ErrorReply> ParseAclSetUser(CmdArgList args) {
157
160
158
161
} // namespace
159
162
163
+ void AclFamily::StreamUpdatesToAllProactorConnections (std::string_view user, uint32_t update_cat) {
164
+ auto update_cb = [user, update_cat]([[maybe_unused]] size_t id, util::Connection* conn) {
165
+ DCHECK (conn);
166
+ auto connection = static_cast <facade::Connection*>(conn);
167
+ auto ctx = static_cast <ConnectionContext*>(connection->cntx ());
168
+ if (ctx && user == ctx->authed_username ) {
169
+ ctx->acl_categories = update_cat;
170
+ }
171
+ };
172
+
173
+ if (main_listener_) {
174
+ main_listener_->TraverseConnections (update_cb);
175
+ }
176
+ }
177
+
160
178
void AclFamily::SetUser (CmdArgList args, ConnectionContext* cntx) {
161
179
std::string_view username = facade::ToSV (args[0 ]);
162
180
auto req = ParseAclSetUser (args.subspan (1 ));
163
181
auto error_case = [cntx](ErrorReply&& error) { (*cntx)->SendError (error); };
164
- auto update_case = [username, cntx](User::UpdateRequest&& req) {
165
- ServerState::tlocal ()->user_registry ->MaybeAddAndUpdate (username, std::move (req));
182
+ auto update_case = [username, cntx, this ](User::UpdateRequest&& req) {
183
+ auto & registry = ServerState::tlocal ()->user_registry ;
184
+ auto user_with_lock = registry->MaybeAddAndUpdateWithLock (username, std::move (req));
185
+ if (user_with_lock.exists ) {
186
+ StreamUpdatesToAllProactorConnections (username, user_with_lock.user .AclCategory ());
187
+ }
166
188
(*cntx)->SendOk ();
167
189
};
168
190
@@ -171,8 +193,15 @@ void AclFamily::SetUser(CmdArgList args, ConnectionContext* cntx) {
171
193
172
194
using CI = dfly::CommandId;
173
195
174
- #define HFUNC (x ) SetHandler(&AclFamily::x)
196
+ using MemberFunc = void (AclFamily::*)(CmdArgList args, ConnectionContext* cntx);
197
+
198
+ inline CommandId::Handler HandlerFunc (AclFamily* acl, MemberFunc f) {
199
+ return [=](CmdArgList args, ConnectionContext* cntx) { return (acl->*f)(args, cntx); };
200
+ }
201
+
202
+ #define HFUNC (x ) SetHandler(HandlerFunc(this , &AclFamily::x))
175
203
204
+ constexpr uint32_t kAcl = acl::CONNECTION;
176
205
constexpr uint32_t kList = acl::ADMIN | acl::SLOW | acl::DANGEROUS;
177
206
constexpr uint32_t kSetUser = acl::ADMIN | acl::SLOW | acl::DANGEROUS;
178
207
@@ -184,7 +213,7 @@ constexpr uint32_t kSetUser = acl::ADMIN | acl::SLOW | acl::DANGEROUS;
184
213
// easy to handle that case explicitly in `DispatchCommand`.
185
214
186
215
void AclFamily::Register (dfly::CommandRegistry* registry) {
187
- *registry << CI{" ACL" , CO::NOSCRIPT | CO::LOADING, 0 , 0 , 0 , 0 , acl::kList }.HFUNC (Acl);
216
+ *registry << CI{" ACL" , CO::NOSCRIPT | CO::LOADING, 0 , 0 , 0 , 0 , acl::kAcl }.HFUNC (Acl);
188
217
*registry << CI{" ACL LIST" , CO::ADMIN | CO::NOSCRIPT | CO::LOADING, 1 , 0 , 0 , 0 , acl::kList }.HFUNC (
189
218
List);
190
219
*registry << CI{" ACL SETUSER" , CO::ADMIN | CO::NOSCRIPT | CO::LOADING, -2 , 0 , 0 , 0 , acl::kSetUser }
@@ -193,4 +222,8 @@ void AclFamily::Register(dfly::CommandRegistry* registry) {
193
222
194
223
#undef HFUNC
195
224
225
+ void AclFamily::Init (facade::Listener* main_listener) {
226
+ main_listener_ = main_listener;
227
+ }
228
+
196
229
} // namespace dfly::acl
0 commit comments