1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
4 #include "common/ceph_json.h"
8 #include "rgw_rest_user.h"
11 #include "include/str_list.h"
12 #include "include/ceph_assert.h"
14 #include "services/svc_zone.h"
15 #include "services/svc_sys_obj.h"
18 #define dout_subsys ceph_subsys_rgw
22 class RGWOp_User_List
: public RGWRESTOp
{
27 int check_caps(const RGWUserCaps
& caps
) override
{
28 return caps
.check_cap("users", RGW_CAP_READ
);
31 void execute(optional_yield y
) override
;
33 const char* name() const override
{ return "list_user"; }
36 void RGWOp_User_List::execute(optional_yield y
)
38 RGWUserAdminOpState
op_state(store
);
42 RESTArgs::get_uint32(s
, "max-entries", 1000, &max_entries
);
43 RESTArgs::get_string(s
, "marker", marker
, &marker
);
45 op_state
.max_entries
= max_entries
;
46 op_state
.marker
= marker
;
47 op_ret
= RGWUserAdminOp_User::list(this, store
, op_state
, flusher
);
50 class RGWOp_User_Info
: public RGWRESTOp
{
55 int check_caps(const RGWUserCaps
& caps
) override
{
56 return caps
.check_cap("users", RGW_CAP_READ
);
59 void execute(optional_yield y
) override
;
61 const char* name() const override
{ return "get_user_info"; }
64 void RGWOp_User_Info::execute(optional_yield y
)
66 RGWUserAdminOpState
op_state(store
);
68 std::string uid_str
, access_key_str
;
72 RESTArgs::get_string(s
, "uid", uid_str
, &uid_str
);
73 RESTArgs::get_string(s
, "access-key", access_key_str
, &access_key_str
);
75 // if uid was not supplied in rest argument, error out now, otherwise we'll
76 // end up initializing anonymous user, for which keys.init will eventually
78 if (uid_str
.empty() && access_key_str
.empty()){
83 rgw_user
uid(uid_str
);
85 RESTArgs::get_bool(s
, "stats", false, &fetch_stats
);
87 RESTArgs::get_bool(s
, "sync", false, &sync_stats
);
89 op_state
.set_user_id(uid
);
90 op_state
.set_access_key(access_key_str
);
91 op_state
.set_fetch_stats(fetch_stats
);
92 op_state
.set_sync_stats(sync_stats
);
94 op_ret
= RGWUserAdminOp_User::info(s
, store
, op_state
, flusher
, y
);
97 class RGWOp_User_Create
: public RGWRESTOp
{
100 RGWOp_User_Create() {}
102 int check_caps(const RGWUserCaps
& caps
) override
{
103 return caps
.check_cap("users", RGW_CAP_WRITE
);
106 void execute(optional_yield y
) override
;
108 const char* name() const override
{ return "create_user"; }
111 void RGWOp_User_Create::execute(optional_yield y
)
114 std::string display_name
;
116 std::string access_key
;
117 std::string secret_key
;
118 std::string key_type_str
;
120 std::string tenant_name
;
121 std::string op_mask_str
;
122 std::string default_placement_str
;
123 std::string placement_tags_str
;
131 const int32_t default_max_buckets
=
132 s
->cct
->_conf
.get_val
<int64_t>("rgw_user_max_buckets");
134 RGWUserAdminOpState
op_state(store
);
136 RESTArgs::get_string(s
, "uid", uid_str
, &uid_str
);
137 rgw_user
uid(uid_str
);
139 RESTArgs::get_string(s
, "display-name", display_name
, &display_name
);
140 RESTArgs::get_string(s
, "email", email
, &email
);
141 RESTArgs::get_string(s
, "access-key", access_key
, &access_key
);
142 RESTArgs::get_string(s
, "secret-key", secret_key
, &secret_key
);
143 RESTArgs::get_string(s
, "key-type", key_type_str
, &key_type_str
);
144 RESTArgs::get_string(s
, "user-caps", caps
, &caps
);
145 RESTArgs::get_string(s
, "tenant", tenant_name
, &tenant_name
);
146 RESTArgs::get_bool(s
, "generate-key", true, &gen_key
);
147 RESTArgs::get_bool(s
, "suspended", false, &suspended
);
148 RESTArgs::get_int32(s
, "max-buckets", default_max_buckets
, &max_buckets
);
149 RESTArgs::get_bool(s
, "system", false, &system
);
150 RESTArgs::get_bool(s
, "exclusive", false, &exclusive
);
151 RESTArgs::get_string(s
, "op-mask", op_mask_str
, &op_mask_str
);
152 RESTArgs::get_string(s
, "default-placement", default_placement_str
, &default_placement_str
);
153 RESTArgs::get_string(s
, "placement-tags", placement_tags_str
, &placement_tags_str
);
155 if (!s
->user
->get_info().system
&& system
) {
156 ldpp_dout(this, 0) << "cannot set system flag by non-system user" << dendl
;
161 if (!tenant_name
.empty()) {
162 uid
.tenant
= tenant_name
;
165 // TODO: validate required args are passed in. (for eg. uid and display_name here)
166 op_state
.set_user_id(uid
);
167 op_state
.set_display_name(display_name
);
168 op_state
.set_user_email(email
);
169 op_state
.set_caps(caps
);
170 op_state
.set_access_key(access_key
);
171 op_state
.set_secret_key(secret_key
);
173 if (!op_mask_str
.empty()) {
175 int ret
= rgw_parse_op_type_list(op_mask_str
, &op_mask
);
177 ldpp_dout(this, 0) << "failed to parse op_mask: " << ret
<< dendl
;
181 op_state
.set_op_mask(op_mask
);
184 if (!key_type_str
.empty()) {
185 int32_t key_type
= KEY_TYPE_UNDEFINED
;
186 if (key_type_str
.compare("swift") == 0)
187 key_type
= KEY_TYPE_SWIFT
;
188 else if (key_type_str
.compare("s3") == 0)
189 key_type
= KEY_TYPE_S3
;
191 op_state
.set_key_type(key_type
);
194 if (max_buckets
!= default_max_buckets
) {
195 if (max_buckets
< 0) {
198 op_state
.set_max_buckets(max_buckets
);
200 if (s
->info
.args
.exists("suspended"))
201 op_state
.set_suspension(suspended
);
203 if (s
->info
.args
.exists("system"))
204 op_state
.set_system(system
);
206 if (s
->info
.args
.exists("exclusive"))
207 op_state
.set_exclusive(exclusive
);
210 op_state
.set_generate_key();
212 if (!default_placement_str
.empty()) {
213 rgw_placement_rule target_rule
;
214 target_rule
.from_str(default_placement_str
);
215 if (!store
->get_zone()->get_params().valid_placement(target_rule
)) {
216 ldpp_dout(this, 0) << "NOTICE: invalid dest placement: " << target_rule
.to_str() << dendl
;
220 op_state
.set_default_placement(target_rule
);
223 if (!placement_tags_str
.empty()) {
224 list
<string
> placement_tags_list
;
225 get_str_list(placement_tags_str
, ",", placement_tags_list
);
226 op_state
.set_placement_tags(placement_tags_list
);
230 op_ret
= store
->forward_request_to_master(s
, s
->user
.get(), nullptr, data
, nullptr, s
->info
, y
);
232 ldpp_dout(this, 0) << "forward_request_to_master returned ret=" << op_ret
<< dendl
;
235 op_ret
= RGWUserAdminOp_User::create(s
, store
, op_state
, flusher
, y
);
238 class RGWOp_User_Modify
: public RGWRESTOp
{
241 RGWOp_User_Modify() {}
243 int check_caps(const RGWUserCaps
& caps
) override
{
244 return caps
.check_cap("users", RGW_CAP_WRITE
);
247 void execute(optional_yield y
) override
;
249 const char* name() const override
{ return "modify_user"; }
252 void RGWOp_User_Modify::execute(optional_yield y
)
255 std::string display_name
;
257 std::string access_key
;
258 std::string secret_key
;
259 std::string key_type_str
;
260 std::string op_mask_str
;
261 std::string default_placement_str
;
262 std::string placement_tags_str
;
271 RGWUserAdminOpState
op_state(store
);
273 RESTArgs::get_string(s
, "uid", uid_str
, &uid_str
);
274 rgw_user
uid(uid_str
);
276 RESTArgs::get_string(s
, "display-name", display_name
, &display_name
);
277 RESTArgs::get_string(s
, "email", email
, &email
, &email_set
);
278 RESTArgs::get_string(s
, "access-key", access_key
, &access_key
);
279 RESTArgs::get_string(s
, "secret-key", secret_key
, &secret_key
);
280 RESTArgs::get_bool(s
, "generate-key", false, &gen_key
);
281 RESTArgs::get_bool(s
, "suspended", false, &suspended
);
282 RESTArgs::get_int32(s
, "max-buckets", RGW_DEFAULT_MAX_BUCKETS
, &max_buckets
, "a_set
);
283 RESTArgs::get_string(s
, "key-type", key_type_str
, &key_type_str
);
285 RESTArgs::get_bool(s
, "system", false, &system
);
286 RESTArgs::get_string(s
, "op-mask", op_mask_str
, &op_mask_str
);
287 RESTArgs::get_string(s
, "default-placement", default_placement_str
, &default_placement_str
);
288 RESTArgs::get_string(s
, "placement-tags", placement_tags_str
, &placement_tags_str
);
290 if (!s
->user
->get_info().system
&& system
) {
291 ldpp_dout(this, 0) << "cannot set system flag by non-system user" << dendl
;
296 op_state
.set_user_id(uid
);
297 op_state
.set_display_name(display_name
);
300 op_state
.set_user_email(email
);
302 op_state
.set_access_key(access_key
);
303 op_state
.set_secret_key(secret_key
);
306 if (max_buckets
< 0 ) {
309 op_state
.set_max_buckets(max_buckets
);
312 op_state
.set_generate_key();
314 if (!key_type_str
.empty()) {
315 int32_t key_type
= KEY_TYPE_UNDEFINED
;
316 if (key_type_str
.compare("swift") == 0)
317 key_type
= KEY_TYPE_SWIFT
;
318 else if (key_type_str
.compare("s3") == 0)
319 key_type
= KEY_TYPE_S3
;
321 op_state
.set_key_type(key_type
);
324 if (!op_mask_str
.empty()) {
326 if (rgw_parse_op_type_list(op_mask_str
, &op_mask
) < 0) {
327 ldpp_dout(this, 0) << "failed to parse op_mask" << dendl
;
331 op_state
.set_op_mask(op_mask
);
334 if (s
->info
.args
.exists("suspended"))
335 op_state
.set_suspension(suspended
);
337 if (s
->info
.args
.exists("system"))
338 op_state
.set_system(system
);
340 if (!op_mask_str
.empty()) {
342 int ret
= rgw_parse_op_type_list(op_mask_str
, &op_mask
);
344 ldpp_dout(this, 0) << "failed to parse op_mask: " << ret
<< dendl
;
348 op_state
.set_op_mask(op_mask
);
351 if (!default_placement_str
.empty()) {
352 rgw_placement_rule target_rule
;
353 target_rule
.from_str(default_placement_str
);
354 if (!store
->get_zone()->get_params().valid_placement(target_rule
)) {
355 ldpp_dout(this, 0) << "NOTICE: invalid dest placement: " << target_rule
.to_str() << dendl
;
359 op_state
.set_default_placement(target_rule
);
362 if (!placement_tags_str
.empty()) {
363 list
<string
> placement_tags_list
;
364 get_str_list(placement_tags_str
, ",", placement_tags_list
);
365 op_state
.set_placement_tags(placement_tags_list
);
369 op_ret
= store
->forward_request_to_master(s
, s
->user
.get(), nullptr, data
, nullptr, s
->info
, y
);
371 ldpp_dout(this, 0) << "forward_request_to_master returned ret=" << op_ret
<< dendl
;
374 op_ret
= RGWUserAdminOp_User::modify(s
, store
, op_state
, flusher
, y
);
377 class RGWOp_User_Remove
: public RGWRESTOp
{
380 RGWOp_User_Remove() {}
382 int check_caps(const RGWUserCaps
& caps
) override
{
383 return caps
.check_cap("users", RGW_CAP_WRITE
);
386 void execute(optional_yield y
) override
;
388 const char* name() const override
{ return "remove_user"; }
391 void RGWOp_User_Remove::execute(optional_yield y
)
396 RGWUserAdminOpState
op_state(store
);
398 RESTArgs::get_string(s
, "uid", uid_str
, &uid_str
);
399 rgw_user
uid(uid_str
);
401 RESTArgs::get_bool(s
, "purge-data", false, &purge_data
);
403 // FIXME: no double checking
405 op_state
.set_user_id(uid
);
407 op_state
.set_purge_data(purge_data
);
410 op_ret
= store
->forward_request_to_master(s
, s
->user
.get(), nullptr, data
, nullptr, s
->info
, y
);
412 ldpp_dout(this, 0) << "forward_request_to_master returned ret=" << op_ret
<< dendl
;
415 op_ret
= RGWUserAdminOp_User::remove(s
, store
, op_state
, flusher
, s
->yield
);
418 class RGWOp_Subuser_Create
: public RGWRESTOp
{
421 RGWOp_Subuser_Create() {}
423 int check_caps(const RGWUserCaps
& caps
) override
{
424 return caps
.check_cap("users", RGW_CAP_WRITE
);
427 void execute(optional_yield y
) override
;
429 const char* name() const override
{ return "create_subuser"; }
432 void RGWOp_Subuser_Create::execute(optional_yield y
)
436 std::string secret_key
;
437 std::string access_key
;
438 std::string perm_str
;
439 std::string key_type_str
;
441 bool gen_subuser
= false; // FIXME placeholder
445 uint32_t perm_mask
= 0;
446 int32_t key_type
= KEY_TYPE_SWIFT
;
448 RGWUserAdminOpState
op_state(store
);
450 RESTArgs::get_string(s
, "uid", uid_str
, &uid_str
);
451 rgw_user
uid(uid_str
);
453 RESTArgs::get_string(s
, "subuser", subuser
, &subuser
);
454 RESTArgs::get_string(s
, "access-key", access_key
, &access_key
);
455 RESTArgs::get_string(s
, "secret-key", secret_key
, &secret_key
);
456 RESTArgs::get_string(s
, "access", perm_str
, &perm_str
);
457 RESTArgs::get_string(s
, "key-type", key_type_str
, &key_type_str
);
458 RESTArgs::get_bool(s
, "generate-secret", false, &gen_secret
);
459 RESTArgs::get_bool(s
, "gen-access-key", false, &gen_access
);
461 perm_mask
= rgw_str_to_perm(perm_str
.c_str());
462 op_state
.set_perm(perm_mask
);
464 op_state
.set_user_id(uid
);
465 op_state
.set_subuser(subuser
);
466 op_state
.set_access_key(access_key
);
467 op_state
.set_secret_key(secret_key
);
468 op_state
.set_generate_subuser(gen_subuser
);
471 op_state
.set_gen_access();
474 op_state
.set_gen_secret();
476 if (!key_type_str
.empty()) {
477 if (key_type_str
.compare("swift") == 0)
478 key_type
= KEY_TYPE_SWIFT
;
479 else if (key_type_str
.compare("s3") == 0)
480 key_type
= KEY_TYPE_S3
;
482 op_state
.set_key_type(key_type
);
485 op_ret
= store
->forward_request_to_master(s
, s
->user
.get(), nullptr, data
, nullptr, s
->info
, y
);
487 ldpp_dout(this, 0) << "forward_request_to_master returned ret=" << op_ret
<< dendl
;
490 op_ret
= RGWUserAdminOp_Subuser::create(s
, store
, op_state
, flusher
, y
);
493 class RGWOp_Subuser_Modify
: public RGWRESTOp
{
496 RGWOp_Subuser_Modify() {}
498 int check_caps(const RGWUserCaps
& caps
) override
{
499 return caps
.check_cap("users", RGW_CAP_WRITE
);
502 void execute(optional_yield y
) override
;
504 const char* name() const override
{ return "modify_subuser"; }
507 void RGWOp_Subuser_Modify::execute(optional_yield y
)
511 std::string secret_key
;
512 std::string key_type_str
;
513 std::string perm_str
;
515 RGWUserAdminOpState
op_state(store
);
518 int32_t key_type
= KEY_TYPE_SWIFT
;
522 RESTArgs::get_string(s
, "uid", uid_str
, &uid_str
);
523 rgw_user
uid(uid_str
);
525 RESTArgs::get_string(s
, "subuser", subuser
, &subuser
);
526 RESTArgs::get_string(s
, "secret-key", secret_key
, &secret_key
);
527 RESTArgs::get_string(s
, "access", perm_str
, &perm_str
);
528 RESTArgs::get_string(s
, "key-type", key_type_str
, &key_type_str
);
529 RESTArgs::get_bool(s
, "generate-secret", false, &gen_secret
);
531 perm_mask
= rgw_str_to_perm(perm_str
.c_str());
532 op_state
.set_perm(perm_mask
);
534 op_state
.set_user_id(uid
);
535 op_state
.set_subuser(subuser
);
537 if (!secret_key
.empty())
538 op_state
.set_secret_key(secret_key
);
541 op_state
.set_gen_secret();
543 if (!key_type_str
.empty()) {
544 if (key_type_str
.compare("swift") == 0)
545 key_type
= KEY_TYPE_SWIFT
;
546 else if (key_type_str
.compare("s3") == 0)
547 key_type
= KEY_TYPE_S3
;
549 op_state
.set_key_type(key_type
);
552 op_ret
= store
->forward_request_to_master(s
, s
->user
.get(), nullptr, data
, nullptr, s
->info
, y
);
554 ldpp_dout(this, 0) << "forward_request_to_master returned ret=" << op_ret
<< dendl
;
557 op_ret
= RGWUserAdminOp_Subuser::modify(s
, store
, op_state
, flusher
, y
);
560 class RGWOp_Subuser_Remove
: public RGWRESTOp
{
563 RGWOp_Subuser_Remove() {}
565 int check_caps(const RGWUserCaps
& caps
) override
{
566 return caps
.check_cap("users", RGW_CAP_WRITE
);
569 void execute(optional_yield y
) override
;
571 const char* name() const override
{ return "remove_subuser"; }
574 void RGWOp_Subuser_Remove::execute(optional_yield y
)
580 RGWUserAdminOpState
op_state(store
);
582 RESTArgs::get_string(s
, "uid", uid_str
, &uid_str
);
583 rgw_user
uid(uid_str
);
585 RESTArgs::get_string(s
, "subuser", subuser
, &subuser
);
586 RESTArgs::get_bool(s
, "purge-keys", true, &purge_keys
);
588 op_state
.set_user_id(uid
);
589 op_state
.set_subuser(subuser
);
592 op_state
.set_purge_keys();
595 op_ret
= store
->forward_request_to_master(s
, s
->user
.get(), nullptr, data
, nullptr, s
->info
, y
);
597 ldpp_dout(this, 0) << "forward_request_to_master returned ret=" << op_ret
<< dendl
;
600 op_ret
= RGWUserAdminOp_Subuser::remove(s
, store
, op_state
, flusher
, y
);
603 class RGWOp_Key_Create
: public RGWRESTOp
{
606 RGWOp_Key_Create() {}
608 int check_caps(const RGWUserCaps
& caps
) override
{
609 return caps
.check_cap("users", RGW_CAP_WRITE
);
612 void execute(optional_yield y
) override
;
614 const char* name() const override
{ return "create_access_key"; }
617 void RGWOp_Key_Create::execute(optional_yield y
)
621 std::string access_key
;
622 std::string secret_key
;
623 std::string key_type_str
;
627 RGWUserAdminOpState
op_state(store
);
629 RESTArgs::get_string(s
, "uid", uid_str
, &uid_str
);
630 rgw_user
uid(uid_str
);
632 RESTArgs::get_string(s
, "subuser", subuser
, &subuser
);
633 RESTArgs::get_string(s
, "access-key", access_key
, &access_key
);
634 RESTArgs::get_string(s
, "secret-key", secret_key
, &secret_key
);
635 RESTArgs::get_string(s
, "key-type", key_type_str
, &key_type_str
);
636 RESTArgs::get_bool(s
, "generate-key", true, &gen_key
);
638 op_state
.set_user_id(uid
);
639 op_state
.set_subuser(subuser
);
640 op_state
.set_access_key(access_key
);
641 op_state
.set_secret_key(secret_key
);
644 op_state
.set_generate_key();
646 if (!key_type_str
.empty()) {
647 int32_t key_type
= KEY_TYPE_UNDEFINED
;
648 if (key_type_str
.compare("swift") == 0)
649 key_type
= KEY_TYPE_SWIFT
;
650 else if (key_type_str
.compare("s3") == 0)
651 key_type
= KEY_TYPE_S3
;
653 op_state
.set_key_type(key_type
);
656 op_ret
= RGWUserAdminOp_Key::create(s
, store
, op_state
, flusher
, y
);
659 class RGWOp_Key_Remove
: public RGWRESTOp
{
662 RGWOp_Key_Remove() {}
664 int check_caps(const RGWUserCaps
& caps
) override
{
665 return caps
.check_cap("users", RGW_CAP_WRITE
);
668 void execute(optional_yield y
) override
;
670 const char* name() const override
{ return "remove_access_key"; }
673 void RGWOp_Key_Remove::execute(optional_yield y
)
677 std::string access_key
;
678 std::string key_type_str
;
680 RGWUserAdminOpState
op_state(store
);
682 RESTArgs::get_string(s
, "uid", uid_str
, &uid_str
);
683 rgw_user
uid(uid_str
);
685 RESTArgs::get_string(s
, "subuser", subuser
, &subuser
);
686 RESTArgs::get_string(s
, "access-key", access_key
, &access_key
);
687 RESTArgs::get_string(s
, "key-type", key_type_str
, &key_type_str
);
689 op_state
.set_user_id(uid
);
690 op_state
.set_subuser(subuser
);
691 op_state
.set_access_key(access_key
);
693 if (!key_type_str
.empty()) {
694 int32_t key_type
= KEY_TYPE_UNDEFINED
;
695 if (key_type_str
.compare("swift") == 0)
696 key_type
= KEY_TYPE_SWIFT
;
697 else if (key_type_str
.compare("s3") == 0)
698 key_type
= KEY_TYPE_S3
;
700 op_state
.set_key_type(key_type
);
703 op_ret
= RGWUserAdminOp_Key::remove(s
, store
, op_state
, flusher
, y
);
706 class RGWOp_Caps_Add
: public RGWRESTOp
{
711 int check_caps(const RGWUserCaps
& caps
) override
{
712 return caps
.check_cap("users", RGW_CAP_WRITE
);
715 void execute(optional_yield y
) override
;
717 const char* name() const override
{ return "add_user_caps"; }
720 void RGWOp_Caps_Add::execute(optional_yield y
)
725 RGWUserAdminOpState
op_state(store
);
727 RESTArgs::get_string(s
, "uid", uid_str
, &uid_str
);
728 rgw_user
uid(uid_str
);
730 RESTArgs::get_string(s
, "user-caps", caps
, &caps
);
732 op_state
.set_user_id(uid
);
733 op_state
.set_caps(caps
);
736 op_ret
= store
->forward_request_to_master(s
, s
->user
.get(), nullptr, data
, nullptr, s
->info
, y
);
738 ldpp_dout(this, 0) << "forward_request_to_master returned ret=" << op_ret
<< dendl
;
741 op_ret
= RGWUserAdminOp_Caps::add(s
, store
, op_state
, flusher
, y
);
744 class RGWOp_Caps_Remove
: public RGWRESTOp
{
747 RGWOp_Caps_Remove() {}
749 int check_caps(const RGWUserCaps
& caps
) override
{
750 return caps
.check_cap("users", RGW_CAP_WRITE
);
753 void execute(optional_yield y
) override
;
755 const char* name() const override
{ return "remove_user_caps"; }
758 void RGWOp_Caps_Remove::execute(optional_yield y
)
763 RGWUserAdminOpState
op_state(store
);
765 RESTArgs::get_string(s
, "uid", uid_str
, &uid_str
);
766 rgw_user
uid(uid_str
);
768 RESTArgs::get_string(s
, "user-caps", caps
, &caps
);
770 op_state
.set_user_id(uid
);
771 op_state
.set_caps(caps
);
774 op_ret
= store
->forward_request_to_master(s
, s
->user
.get(), nullptr, data
, nullptr, s
->info
, y
);
776 ldpp_dout(this, 0) << "forward_request_to_master returned ret=" << op_ret
<< dendl
;
779 op_ret
= RGWUserAdminOp_Caps::remove(s
, store
, op_state
, flusher
, y
);
783 RGWQuotaInfo bucket_quota
;
784 RGWQuotaInfo user_quota
;
788 explicit UserQuotas(RGWUserInfo
& info
) : bucket_quota(info
.bucket_quota
),
789 user_quota(info
.user_quota
) {}
791 void dump(Formatter
*f
) const {
792 encode_json("bucket_quota", bucket_quota
, f
);
793 encode_json("user_quota", user_quota
, f
);
795 void decode_json(JSONObj
*obj
) {
796 JSONDecoder::decode_json("bucket_quota", bucket_quota
, obj
);
797 JSONDecoder::decode_json("user_quota", user_quota
, obj
);
801 class RGWOp_Quota_Info
: public RGWRESTOp
{
804 RGWOp_Quota_Info() {}
806 int check_caps(const RGWUserCaps
& caps
) override
{
807 return caps
.check_cap("users", RGW_CAP_READ
);
810 void execute(optional_yield y
) override
;
812 const char* name() const override
{ return "get_quota_info"; }
816 void RGWOp_Quota_Info::execute(optional_yield y
)
818 RGWUserAdminOpState
op_state(store
);
821 std::string quota_type
;
823 RESTArgs::get_string(s
, "uid", uid_str
, &uid_str
);
824 RESTArgs::get_string(s
, "quota-type", quota_type
, "a_type
);
826 if (uid_str
.empty()) {
831 rgw_user
uid(uid_str
);
833 bool show_all
= quota_type
.empty();
834 bool show_bucket
= show_all
|| (quota_type
== "bucket");
835 bool show_user
= show_all
|| (quota_type
== "user");
837 if (!(show_all
|| show_bucket
|| show_user
)) {
842 op_state
.set_user_id(uid
);
845 op_ret
= user
.init(s
, store
, op_state
, y
);
849 if (!op_state
.has_existing_user()) {
850 op_ret
= -ERR_NO_SUCH_USER
;
856 op_ret
= user
.info(info
, &err_msg
);
862 UserQuotas
quotas(info
);
863 encode_json("quota", quotas
, s
->formatter
);
864 } else if (show_user
) {
865 encode_json("user_quota", info
.user_quota
, s
->formatter
);
867 encode_json("bucket_quota", info
.bucket_quota
, s
->formatter
);
873 class RGWOp_Quota_Set
: public RGWRESTOp
{
878 int check_caps(const RGWUserCaps
& caps
) override
{
879 return caps
.check_cap("users", RGW_CAP_WRITE
);
882 void execute(optional_yield y
) override
;
884 const char* name() const override
{ return "set_quota_info"; }
890 * two different ways to set the quota info: as json struct in the message body or via http params.
894 * PUT /admin/user?uid=<uid>["a-type=<type>]
896 * whereas quota-type is optional and is either user, or bucket
898 * if quota-type is not specified then we expect to get a structure that contains both quotas,
899 * otherwise we'll only get the relevant configuration.
901 * E.g., if quota type not specified:
904 * "max_size_kb" : 4096,
905 * "max_objects" : -1,
909 * "max_size_kb" : 1024,
910 * "max_objects" : -1,
916 * or if quota type is specified:
918 * "max_size_kb" : 4096,
919 * "max_objects" : -1,
923 * Another option is not to pass any body and set the following http params:
927 * max-objects=<max objects>
928 * enabled[={true,false}]
930 * all params are optionals and default to the current settings. With this type of configuration the
931 * quota-type param is mandatory.
935 void RGWOp_Quota_Set::execute(optional_yield y
)
937 RGWUserAdminOpState
op_state(store
);
940 std::string quota_type
;
942 RESTArgs::get_string(s
, "uid", uid_str
, &uid_str
);
943 RESTArgs::get_string(s
, "quota-type", quota_type
, "a_type
);
945 if (uid_str
.empty()) {
950 rgw_user
uid(uid_str
);
952 bool set_all
= quota_type
.empty();
953 bool set_bucket
= set_all
|| (quota_type
== "bucket");
954 bool set_user
= set_all
|| (quota_type
== "user");
956 if (!(set_all
|| set_bucket
|| set_user
)) {
957 ldpp_dout(this, 20) << "invalid quota type" << dendl
;
962 bool use_http_params
;
964 if (s
->content_length
> 0) {
965 use_http_params
= false;
967 const char *encoding
= s
->info
.env
->get("HTTP_TRANSFER_ENCODING");
968 use_http_params
= (!encoding
|| strcmp(encoding
, "chunked") != 0);
971 if (use_http_params
&& set_all
) {
972 ldpp_dout(this, 20) << "quota type was not specified, can't set all quotas via http headers" << dendl
;
977 op_state
.set_user_id(uid
);
980 op_ret
= user
.init(s
, store
, op_state
, y
);
982 ldpp_dout(this, 20) << "failed initializing user info: " << op_ret
<< dendl
;
986 if (!op_state
.has_existing_user()) {
987 op_ret
= -ERR_NO_SUCH_USER
;
991 #define QUOTA_INPUT_MAX_LEN 1024
995 if ((op_ret
= get_json_input(store
->ctx(), s
, quotas
, QUOTA_INPUT_MAX_LEN
, NULL
)) < 0) {
996 ldpp_dout(this, 20) << "failed to retrieve input" << dendl
;
1000 op_state
.set_user_quota(quotas
.user_quota
);
1001 op_state
.set_bucket_quota(quotas
.bucket_quota
);
1005 if (!use_http_params
) {
1007 op_ret
= get_json_input(store
->ctx(), s
, quota
, QUOTA_INPUT_MAX_LEN
, &empty
);
1009 ldpp_dout(this, 20) << "failed to retrieve input" << dendl
;
1013 /* was probably chunked input, but no content provided, configure via http params */
1014 use_http_params
= true;
1018 if (use_http_params
) {
1021 op_ret
= user
.info(info
, &err_msg
);
1023 ldpp_dout(this, 20) << "failed to get user info: " << op_ret
<< dendl
;
1026 RGWQuotaInfo
*old_quota
;
1028 old_quota
= &info
.user_quota
;
1030 old_quota
= &info
.bucket_quota
;
1033 RESTArgs::get_int64(s
, "max-objects", old_quota
->max_objects
, "a
.max_objects
);
1034 RESTArgs::get_int64(s
, "max-size", old_quota
->max_size
, "a
.max_size
);
1035 int64_t max_size_kb
;
1036 bool has_max_size_kb
= false;
1037 RESTArgs::get_int64(s
, "max-size-kb", 0, &max_size_kb
, &has_max_size_kb
);
1038 if (has_max_size_kb
) {
1039 quota
.max_size
= max_size_kb
* 1024;
1041 RESTArgs::get_bool(s
, "enabled", old_quota
->enabled
, "a
.enabled
);
1045 op_state
.set_user_quota(quota
);
1047 op_state
.set_bucket_quota(quota
);
1052 op_ret
= user
.modify(s
, op_state
, y
, &err
);
1054 ldpp_dout(this, 20) << "failed updating user info: " << op_ret
<< ": " << err
<< dendl
;
1059 RGWOp
*RGWHandler_User::op_get()
1061 if (s
->info
.args
.sub_resource_exists("quota"))
1062 return new RGWOp_Quota_Info
;
1064 if (s
->info
.args
.sub_resource_exists("list"))
1065 return new RGWOp_User_List
;
1067 return new RGWOp_User_Info
;
1070 RGWOp
*RGWHandler_User::op_put()
1072 if (s
->info
.args
.sub_resource_exists("subuser"))
1073 return new RGWOp_Subuser_Create
;
1075 if (s
->info
.args
.sub_resource_exists("key"))
1076 return new RGWOp_Key_Create
;
1078 if (s
->info
.args
.sub_resource_exists("caps"))
1079 return new RGWOp_Caps_Add
;
1081 if (s
->info
.args
.sub_resource_exists("quota"))
1082 return new RGWOp_Quota_Set
;
1084 return new RGWOp_User_Create
;
1087 RGWOp
*RGWHandler_User::op_post()
1089 if (s
->info
.args
.sub_resource_exists("subuser"))
1090 return new RGWOp_Subuser_Modify
;
1092 return new RGWOp_User_Modify
;
1095 RGWOp
*RGWHandler_User::op_delete()
1097 if (s
->info
.args
.sub_resource_exists("subuser"))
1098 return new RGWOp_Subuser_Remove
;
1100 if (s
->info
.args
.sub_resource_exists("key"))
1101 return new RGWOp_Key_Remove
;
1103 if (s
->info
.args
.sub_resource_exists("caps"))
1104 return new RGWOp_Caps_Remove
;
1106 return new RGWOp_User_Remove
;