]> git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_rest_user.cc
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / rgw / rgw_rest_user.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #include "common/ceph_json.h"
5
6 #include "rgw_op.h"
7 #include "rgw_user.h"
8 #include "rgw_rest_user.h"
9
10 #include "include/str_list.h"
11 #include "include/ceph_assert.h"
12
13 #define dout_subsys ceph_subsys_rgw
14
15 class RGWOp_User_List : public RGWRESTOp {
16
17 public:
18 RGWOp_User_List() {}
19
20 int check_caps(RGWUserCaps& caps) override {
21 return caps.check_cap("users", RGW_CAP_READ);
22 }
23
24 void execute() override;
25
26 const char* name() const override { return "list_user"; }
27 };
28
29 void RGWOp_User_List::execute()
30 {
31 RGWUserAdminOpState op_state;
32
33 uint32_t max_entries;
34 std::string marker;
35 RESTArgs::get_uint32(s, "max-entries", 1000, &max_entries);
36 RESTArgs::get_string(s, "marker", marker, &marker);
37
38 op_state.max_entries = max_entries;
39 op_state.marker = marker;
40 http_ret = RGWUserAdminOp_User::list(store, op_state, flusher);
41 }
42
43 class RGWOp_User_Info : public RGWRESTOp {
44
45 public:
46 RGWOp_User_Info() {}
47
48 int check_caps(RGWUserCaps& caps) override {
49 return caps.check_cap("users", RGW_CAP_READ);
50 }
51
52 void execute() override;
53
54 const char* name() const override { return "get_user_info"; }
55 };
56
57 void RGWOp_User_Info::execute()
58 {
59 RGWUserAdminOpState op_state;
60
61 std::string uid_str, access_key_str;
62 bool fetch_stats;
63 bool sync_stats;
64
65 RESTArgs::get_string(s, "uid", uid_str, &uid_str);
66 RESTArgs::get_string(s, "access-key", access_key_str, &access_key_str);
67
68 // if uid was not supplied in rest argument, error out now, otherwise we'll
69 // end up initializing anonymous user, for which keys.init will eventually
70 // return -EACESS
71 if (uid_str.empty() && access_key_str.empty()){
72 http_ret=-EINVAL;
73 return;
74 }
75
76 rgw_user uid(uid_str);
77
78 RESTArgs::get_bool(s, "stats", false, &fetch_stats);
79
80 RESTArgs::get_bool(s, "sync", false, &sync_stats);
81
82 op_state.set_user_id(uid);
83 op_state.set_access_key(access_key_str);
84 op_state.set_fetch_stats(fetch_stats);
85 op_state.set_sync_stats(sync_stats);
86
87 http_ret = RGWUserAdminOp_User::info(store, op_state, flusher);
88 }
89
90 class RGWOp_User_Create : public RGWRESTOp {
91
92 public:
93 RGWOp_User_Create() {}
94
95 int check_caps(RGWUserCaps& caps) override {
96 return caps.check_cap("users", RGW_CAP_WRITE);
97 }
98
99 void execute() override;
100
101 const char* name() const override { return "create_user"; }
102 };
103
104 void RGWOp_User_Create::execute()
105 {
106 std::string uid_str;
107 std::string display_name;
108 std::string email;
109 std::string access_key;
110 std::string secret_key;
111 std::string key_type_str;
112 std::string caps;
113 std::string tenant_name;
114 std::string op_mask_str;
115
116 bool gen_key;
117 bool suspended;
118 bool system;
119 bool exclusive;
120
121 int32_t max_buckets;
122 int32_t default_max_buckets = s->cct->_conf->rgw_user_max_buckets;
123
124 RGWUserAdminOpState op_state;
125
126 RESTArgs::get_string(s, "uid", uid_str, &uid_str);
127 rgw_user uid(uid_str);
128
129 RESTArgs::get_string(s, "display-name", display_name, &display_name);
130 RESTArgs::get_string(s, "email", email, &email);
131 RESTArgs::get_string(s, "access-key", access_key, &access_key);
132 RESTArgs::get_string(s, "secret-key", secret_key, &secret_key);
133 RESTArgs::get_string(s, "key-type", key_type_str, &key_type_str);
134 RESTArgs::get_string(s, "user-caps", caps, &caps);
135 RESTArgs::get_string(s, "tenant", tenant_name, &tenant_name);
136 RESTArgs::get_bool(s, "generate-key", true, &gen_key);
137 RESTArgs::get_bool(s, "suspended", false, &suspended);
138 RESTArgs::get_int32(s, "max-buckets", default_max_buckets, &max_buckets);
139 RESTArgs::get_bool(s, "system", false, &system);
140 RESTArgs::get_bool(s, "exclusive", false, &exclusive);
141 RESTArgs::get_string(s, "op-mask", op_mask_str, &op_mask_str);
142
143 if (!s->user->system && system) {
144 ldout(s->cct, 0) << "cannot set system flag by non-system user" << dendl;
145 http_ret = -EINVAL;
146 return;
147 }
148
149 if (!tenant_name.empty()) {
150 uid.tenant = tenant_name;
151 }
152
153 // TODO: validate required args are passed in. (for eg. uid and display_name here)
154 op_state.set_user_id(uid);
155 op_state.set_display_name(display_name);
156 op_state.set_user_email(email);
157 op_state.set_caps(caps);
158 op_state.set_access_key(access_key);
159 op_state.set_secret_key(secret_key);
160
161 if (!op_mask_str.empty()) {
162 uint32_t op_mask;
163 int ret = rgw_parse_op_type_list(op_mask_str, &op_mask);
164 if (ret < 0) {
165 ldout(s->cct, 0) << "failed to parse op_mask: " << ret << dendl;
166 http_ret = -EINVAL;
167 return;
168 }
169 op_state.set_op_mask(op_mask);
170 }
171
172 if (!key_type_str.empty()) {
173 int32_t key_type = KEY_TYPE_UNDEFINED;
174 if (key_type_str.compare("swift") == 0)
175 key_type = KEY_TYPE_SWIFT;
176 else if (key_type_str.compare("s3") == 0)
177 key_type = KEY_TYPE_S3;
178
179 op_state.set_key_type(key_type);
180 }
181
182 if (max_buckets != default_max_buckets)
183 op_state.set_max_buckets(max_buckets);
184
185 if (s->info.args.exists("suspended"))
186 op_state.set_suspension(suspended);
187
188 if (s->info.args.exists("system"))
189 op_state.set_system(system);
190
191 if (s->info.args.exists("exclusive"))
192 op_state.set_exclusive(exclusive);
193
194 if (gen_key)
195 op_state.set_generate_key();
196
197 http_ret = RGWUserAdminOp_User::create(store, op_state, flusher);
198 }
199
200 class RGWOp_User_Modify : public RGWRESTOp {
201
202 public:
203 RGWOp_User_Modify() {}
204
205 int check_caps(RGWUserCaps& caps) override {
206 return caps.check_cap("users", RGW_CAP_WRITE);
207 }
208
209 void execute() override;
210
211 const char* name() const override { return "modify_user"; }
212 };
213
214 void RGWOp_User_Modify::execute()
215 {
216 std::string uid_str;
217 std::string display_name;
218 std::string email;
219 std::string access_key;
220 std::string secret_key;
221 std::string key_type_str;
222 std::string caps;
223 std::string op_mask_str;
224
225 bool gen_key;
226 bool suspended;
227 bool system;
228 bool email_set;
229 bool quota_set;
230 int32_t max_buckets;
231
232 RGWUserAdminOpState op_state;
233
234 RESTArgs::get_string(s, "uid", uid_str, &uid_str);
235 rgw_user uid(uid_str);
236
237 RESTArgs::get_string(s, "display-name", display_name, &display_name);
238 RESTArgs::get_string(s, "email", email, &email, &email_set);
239 RESTArgs::get_string(s, "access-key", access_key, &access_key);
240 RESTArgs::get_string(s, "secret-key", secret_key, &secret_key);
241 RESTArgs::get_string(s, "user-caps", caps, &caps);
242 RESTArgs::get_bool(s, "generate-key", false, &gen_key);
243 RESTArgs::get_bool(s, "suspended", false, &suspended);
244 RESTArgs::get_int32(s, "max-buckets", RGW_DEFAULT_MAX_BUCKETS, &max_buckets, &quota_set);
245 RESTArgs::get_string(s, "key-type", key_type_str, &key_type_str);
246
247 RESTArgs::get_bool(s, "system", false, &system);
248 RESTArgs::get_string(s, "op-mask", op_mask_str, &op_mask_str);
249
250 if (!s->user->system && system) {
251 ldout(s->cct, 0) << "cannot set system flag by non-system user" << dendl;
252 http_ret = -EINVAL;
253 return;
254 }
255
256 op_state.set_user_id(uid);
257 op_state.set_display_name(display_name);
258
259 if (email_set)
260 op_state.set_user_email(email);
261
262 op_state.set_caps(caps);
263 op_state.set_access_key(access_key);
264 op_state.set_secret_key(secret_key);
265
266 if (quota_set)
267 op_state.set_max_buckets(max_buckets);
268
269 if (gen_key)
270 op_state.set_generate_key();
271
272 if (!key_type_str.empty()) {
273 int32_t key_type = KEY_TYPE_UNDEFINED;
274 if (key_type_str.compare("swift") == 0)
275 key_type = KEY_TYPE_SWIFT;
276 else if (key_type_str.compare("s3") == 0)
277 key_type = KEY_TYPE_S3;
278
279 op_state.set_key_type(key_type);
280 }
281
282 if (s->info.args.exists("suspended"))
283 op_state.set_suspension(suspended);
284
285 if (s->info.args.exists("system"))
286 op_state.set_system(system);
287
288 if (!op_mask_str.empty()) {
289 uint32_t op_mask;
290 int ret = rgw_parse_op_type_list(op_mask_str, &op_mask);
291 if (ret < 0) {
292 ldout(s->cct, 0) << "failed to parse op_mask: " << ret << dendl;
293 http_ret = -EINVAL;
294 return;
295 }
296 op_state.set_op_mask(op_mask);
297 }
298
299 http_ret = RGWUserAdminOp_User::modify(store, op_state, flusher);
300 }
301
302 class RGWOp_User_Remove : public RGWRESTOp {
303
304 public:
305 RGWOp_User_Remove() {}
306
307 int check_caps(RGWUserCaps& caps) override {
308 return caps.check_cap("users", RGW_CAP_WRITE);
309 }
310
311 void execute() override;
312
313 const char* name() const override { return "remove_user"; }
314 };
315
316 void RGWOp_User_Remove::execute()
317 {
318 std::string uid_str;
319 bool purge_data;
320
321 RGWUserAdminOpState op_state;
322
323 RESTArgs::get_string(s, "uid", uid_str, &uid_str);
324 rgw_user uid(uid_str);
325
326 RESTArgs::get_bool(s, "purge-data", false, &purge_data);
327
328 // FIXME: no double checking
329 if (!uid.empty())
330 op_state.set_user_id(uid);
331
332 op_state.set_purge_data(purge_data);
333
334 http_ret = RGWUserAdminOp_User::remove(store, op_state, flusher);
335 }
336
337 class RGWOp_Subuser_Create : public RGWRESTOp {
338
339 public:
340 RGWOp_Subuser_Create() {}
341
342 int check_caps(RGWUserCaps& caps) override {
343 return caps.check_cap("users", RGW_CAP_WRITE);
344 }
345
346 void execute() override;
347
348 const char* name() const override { return "create_subuser"; }
349 };
350
351 void RGWOp_Subuser_Create::execute()
352 {
353 std::string uid_str;
354 std::string subuser;
355 std::string secret_key;
356 std::string access_key;
357 std::string perm_str;
358 std::string key_type_str;
359
360 bool gen_subuser = false; // FIXME placeholder
361 bool gen_secret;
362 bool gen_access;
363
364 uint32_t perm_mask = 0;
365 int32_t key_type = KEY_TYPE_SWIFT;
366
367 RGWUserAdminOpState op_state;
368
369 RESTArgs::get_string(s, "uid", uid_str, &uid_str);
370 rgw_user uid(uid_str);
371
372 RESTArgs::get_string(s, "subuser", subuser, &subuser);
373 RESTArgs::get_string(s, "access-key", access_key, &access_key);
374 RESTArgs::get_string(s, "secret-key", secret_key, &secret_key);
375 RESTArgs::get_string(s, "access", perm_str, &perm_str);
376 RESTArgs::get_string(s, "key-type", key_type_str, &key_type_str);
377 //RESTArgs::get_bool(s, "generate-subuser", false, &gen_subuser);
378 RESTArgs::get_bool(s, "generate-secret", false, &gen_secret);
379 RESTArgs::get_bool(s, "gen-access-key", false, &gen_access);
380
381 perm_mask = rgw_str_to_perm(perm_str.c_str());
382 op_state.set_perm(perm_mask);
383
384 op_state.set_user_id(uid);
385 op_state.set_subuser(subuser);
386 op_state.set_access_key(access_key);
387 op_state.set_secret_key(secret_key);
388 op_state.set_generate_subuser(gen_subuser);
389
390 if (gen_access)
391 op_state.set_gen_access();
392
393 if (gen_secret)
394 op_state.set_gen_secret();
395
396 if (!key_type_str.empty()) {
397 if (key_type_str.compare("swift") == 0)
398 key_type = KEY_TYPE_SWIFT;
399 else if (key_type_str.compare("s3") == 0)
400 key_type = KEY_TYPE_S3;
401 }
402 op_state.set_key_type(key_type);
403
404 http_ret = RGWUserAdminOp_Subuser::create(store, op_state, flusher);
405 }
406
407 class RGWOp_Subuser_Modify : public RGWRESTOp {
408
409 public:
410 RGWOp_Subuser_Modify() {}
411
412 int check_caps(RGWUserCaps& caps) override {
413 return caps.check_cap("users", RGW_CAP_WRITE);
414 }
415
416 void execute() override;
417
418 const char* name() const override { return "modify_subuser"; }
419 };
420
421 void RGWOp_Subuser_Modify::execute()
422 {
423 std::string uid_str;
424 std::string subuser;
425 std::string secret_key;
426 std::string key_type_str;
427 std::string perm_str;
428
429 RGWUserAdminOpState op_state;
430
431 uint32_t perm_mask;
432 int32_t key_type = KEY_TYPE_SWIFT;
433
434 bool gen_secret;
435
436 RESTArgs::get_string(s, "uid", uid_str, &uid_str);
437 rgw_user uid(uid_str);
438
439 RESTArgs::get_string(s, "subuser", subuser, &subuser);
440 RESTArgs::get_string(s, "secret-key", secret_key, &secret_key);
441 RESTArgs::get_string(s, "access", perm_str, &perm_str);
442 RESTArgs::get_string(s, "key-type", key_type_str, &key_type_str);
443 RESTArgs::get_bool(s, "generate-secret", false, &gen_secret);
444
445 perm_mask = rgw_str_to_perm(perm_str.c_str());
446 op_state.set_perm(perm_mask);
447
448 op_state.set_user_id(uid);
449 op_state.set_subuser(subuser);
450
451 if (!secret_key.empty())
452 op_state.set_secret_key(secret_key);
453
454 if (gen_secret)
455 op_state.set_gen_secret();
456
457 if (!key_type_str.empty()) {
458 if (key_type_str.compare("swift") == 0)
459 key_type = KEY_TYPE_SWIFT;
460 else if (key_type_str.compare("s3") == 0)
461 key_type = KEY_TYPE_S3;
462 }
463 op_state.set_key_type(key_type);
464
465 http_ret = RGWUserAdminOp_Subuser::modify(store, op_state, flusher);
466 }
467
468 class RGWOp_Subuser_Remove : public RGWRESTOp {
469
470 public:
471 RGWOp_Subuser_Remove() {}
472
473 int check_caps(RGWUserCaps& caps) override {
474 return caps.check_cap("users", RGW_CAP_WRITE);
475 }
476
477 void execute() override;
478
479 const char* name() const override { return "remove_subuser"; }
480 };
481
482 void RGWOp_Subuser_Remove::execute()
483 {
484 std::string uid_str;
485 std::string subuser;
486 bool purge_keys;
487
488 RGWUserAdminOpState op_state;
489
490 RESTArgs::get_string(s, "uid", uid_str, &uid_str);
491 rgw_user uid(uid_str);
492
493 RESTArgs::get_string(s, "subuser", subuser, &subuser);
494 RESTArgs::get_bool(s, "purge-keys", true, &purge_keys);
495
496 op_state.set_user_id(uid);
497 op_state.set_subuser(subuser);
498
499 if (purge_keys)
500 op_state.set_purge_keys();
501
502 http_ret = RGWUserAdminOp_Subuser::remove(store, op_state, flusher);
503 }
504
505 class RGWOp_Key_Create : public RGWRESTOp {
506
507 public:
508 RGWOp_Key_Create() {}
509
510 int check_caps(RGWUserCaps& caps) override {
511 return caps.check_cap("users", RGW_CAP_WRITE);
512 }
513
514 void execute() override;
515
516 const char* name() const override { return "create_access_key"; }
517 };
518
519 void RGWOp_Key_Create::execute()
520 {
521 std::string uid_str;
522 std::string subuser;
523 std::string access_key;
524 std::string secret_key;
525 std::string key_type_str;
526
527 bool gen_key;
528
529 RGWUserAdminOpState op_state;
530
531 RESTArgs::get_string(s, "uid", uid_str, &uid_str);
532 rgw_user uid(uid_str);
533
534 RESTArgs::get_string(s, "subuser", subuser, &subuser);
535 RESTArgs::get_string(s, "access-key", access_key, &access_key);
536 RESTArgs::get_string(s, "secret-key", secret_key, &secret_key);
537 RESTArgs::get_string(s, "key-type", key_type_str, &key_type_str);
538 RESTArgs::get_bool(s, "generate-key", true, &gen_key);
539
540 op_state.set_user_id(uid);
541 op_state.set_subuser(subuser);
542 op_state.set_access_key(access_key);
543 op_state.set_secret_key(secret_key);
544
545 if (gen_key)
546 op_state.set_generate_key();
547
548 if (!key_type_str.empty()) {
549 int32_t key_type = KEY_TYPE_UNDEFINED;
550 if (key_type_str.compare("swift") == 0)
551 key_type = KEY_TYPE_SWIFT;
552 else if (key_type_str.compare("s3") == 0)
553 key_type = KEY_TYPE_S3;
554
555 op_state.set_key_type(key_type);
556 }
557
558 http_ret = RGWUserAdminOp_Key::create(store, op_state, flusher);
559 }
560
561 class RGWOp_Key_Remove : public RGWRESTOp {
562
563 public:
564 RGWOp_Key_Remove() {}
565
566 int check_caps(RGWUserCaps& caps) override {
567 return caps.check_cap("users", RGW_CAP_WRITE);
568 }
569
570 void execute() override;
571
572 const char* name() const override { return "remove_access_key"; }
573 };
574
575 void RGWOp_Key_Remove::execute()
576 {
577 std::string uid_str;
578 std::string subuser;
579 std::string access_key;
580 std::string key_type_str;
581
582 RGWUserAdminOpState op_state;
583
584 RESTArgs::get_string(s, "uid", uid_str, &uid_str);
585 rgw_user uid(uid_str);
586
587 RESTArgs::get_string(s, "subuser", subuser, &subuser);
588 RESTArgs::get_string(s, "access-key", access_key, &access_key);
589 RESTArgs::get_string(s, "key-type", key_type_str, &key_type_str);
590
591 op_state.set_user_id(uid);
592 op_state.set_subuser(subuser);
593 op_state.set_access_key(access_key);
594
595 if (!key_type_str.empty()) {
596 int32_t key_type = KEY_TYPE_UNDEFINED;
597 if (key_type_str.compare("swift") == 0)
598 key_type = KEY_TYPE_SWIFT;
599 else if (key_type_str.compare("s3") == 0)
600 key_type = KEY_TYPE_S3;
601
602 op_state.set_key_type(key_type);
603 }
604
605 http_ret = RGWUserAdminOp_Key::remove(store, op_state, flusher);
606 }
607
608 class RGWOp_Caps_Add : public RGWRESTOp {
609
610 public:
611 RGWOp_Caps_Add() {}
612
613 int check_caps(RGWUserCaps& caps) override {
614 return caps.check_cap("users", RGW_CAP_WRITE);
615 }
616
617 void execute() override;
618
619 const char* name() const override { return "add_user_caps"; }
620 };
621
622 void RGWOp_Caps_Add::execute()
623 {
624 std::string uid_str;
625 std::string caps;
626
627 RGWUserAdminOpState op_state;
628
629 RESTArgs::get_string(s, "uid", uid_str, &uid_str);
630 rgw_user uid(uid_str);
631
632 RESTArgs::get_string(s, "user-caps", caps, &caps);
633
634 op_state.set_user_id(uid);
635 op_state.set_caps(caps);
636
637 http_ret = RGWUserAdminOp_Caps::add(store, op_state, flusher);
638 }
639
640 class RGWOp_Caps_Remove : public RGWRESTOp {
641
642 public:
643 RGWOp_Caps_Remove() {}
644
645 int check_caps(RGWUserCaps& caps) override {
646 return caps.check_cap("users", RGW_CAP_WRITE);
647 }
648
649 void execute() override;
650
651 const char* name() const override { return "remove_user_caps"; }
652 };
653
654 void RGWOp_Caps_Remove::execute()
655 {
656 std::string uid_str;
657 std::string caps;
658
659 RGWUserAdminOpState op_state;
660
661 RESTArgs::get_string(s, "uid", uid_str, &uid_str);
662 rgw_user uid(uid_str);
663
664 RESTArgs::get_string(s, "user-caps", caps, &caps);
665
666 op_state.set_user_id(uid);
667 op_state.set_caps(caps);
668
669 http_ret = RGWUserAdminOp_Caps::remove(store, op_state, flusher);
670 }
671
672 struct UserQuotas {
673 RGWQuotaInfo bucket_quota;
674 RGWQuotaInfo user_quota;
675
676 UserQuotas() {}
677
678 explicit UserQuotas(RGWUserInfo& info) : bucket_quota(info.bucket_quota),
679 user_quota(info.user_quota) {}
680
681 void dump(Formatter *f) const {
682 encode_json("bucket_quota", bucket_quota, f);
683 encode_json("user_quota", user_quota, f);
684 }
685 void decode_json(JSONObj *obj) {
686 JSONDecoder::decode_json("bucket_quota", bucket_quota, obj);
687 JSONDecoder::decode_json("user_quota", user_quota, obj);
688 }
689 };
690
691 class RGWOp_Quota_Info : public RGWRESTOp {
692
693 public:
694 RGWOp_Quota_Info() {}
695
696 int check_caps(RGWUserCaps& caps) override {
697 return caps.check_cap("users", RGW_CAP_READ);
698 }
699
700 void execute() override;
701
702 const char* name() const override { return "get_quota_info"; }
703 };
704
705
706 void RGWOp_Quota_Info::execute()
707 {
708 RGWUserAdminOpState op_state;
709
710 std::string uid_str;
711 std::string quota_type;
712
713 RESTArgs::get_string(s, "uid", uid_str, &uid_str);
714 RESTArgs::get_string(s, "quota-type", quota_type, &quota_type);
715
716 if (uid_str.empty()) {
717 http_ret = -EINVAL;
718 return;
719 }
720
721 rgw_user uid(uid_str);
722
723 bool show_all = quota_type.empty();
724 bool show_bucket = show_all || (quota_type == "bucket");
725 bool show_user = show_all || (quota_type == "user");
726
727 if (!(show_all || show_bucket || show_user)) {
728 http_ret = -EINVAL;
729 return;
730 }
731
732 op_state.set_user_id(uid);
733
734 RGWUser user;
735 http_ret = user.init(store, op_state);
736 if (http_ret < 0)
737 return;
738
739 if (!op_state.has_existing_user()) {
740 http_ret = -ERR_NO_SUCH_USER;
741 return;
742 }
743
744 RGWUserInfo info;
745 string err_msg;
746 http_ret = user.info(info, &err_msg);
747 if (http_ret < 0)
748 return;
749
750 flusher.start(0);
751 if (show_all) {
752 UserQuotas quotas(info);
753 encode_json("quota", quotas, s->formatter);
754 } else if (show_user) {
755 encode_json("user_quota", info.user_quota, s->formatter);
756 } else {
757 encode_json("bucket_quota", info.bucket_quota, s->formatter);
758 }
759
760 flusher.flush();
761 }
762
763 class RGWOp_Quota_Set : public RGWRESTOp {
764
765 public:
766 RGWOp_Quota_Set() {}
767
768 int check_caps(RGWUserCaps& caps) override {
769 return caps.check_cap("users", RGW_CAP_WRITE);
770 }
771
772 void execute() override;
773
774 const char* name() const override { return "set_quota_info"; }
775 };
776
777 /**
778 * set quota
779 *
780 * two different ways to set the quota info: as json struct in the message body or via http params.
781 *
782 * as json:
783 *
784 * PUT /admin/user?uid=<uid>[&quota-type=<type>]
785 *
786 * whereas quota-type is optional and is either user, or bucket
787 *
788 * if quota-type is not specified then we expect to get a structure that contains both quotas,
789 * otherwise we'll only get the relevant configuration.
790 *
791 * E.g., if quota type not specified:
792 * {
793 * "user_quota" : {
794 * "max_size_kb" : 4096,
795 * "max_objects" : -1,
796 * "enabled" : false
797 * },
798 * "bucket_quota" : {
799 * "max_size_kb" : 1024,
800 * "max_objects" : -1,
801 * "enabled" : true
802 * }
803 * }
804 *
805 *
806 * or if quota type is specified:
807 * {
808 * "max_size_kb" : 4096,
809 * "max_objects" : -1,
810 * "enabled" : false
811 * }
812 *
813 * Another option is not to pass any body and set the following http params:
814 *
815 *
816 * max-size-kb=<size>
817 * max-objects=<max objects>
818 * enabled[={true,false}]
819 *
820 * all params are optionals and default to the current settings. With this type of configuration the
821 * quota-type param is mandatory.
822 *
823 */
824
825 void RGWOp_Quota_Set::execute()
826 {
827 RGWUserAdminOpState op_state;
828
829 std::string uid_str;
830 std::string quota_type;
831
832 RESTArgs::get_string(s, "uid", uid_str, &uid_str);
833 RESTArgs::get_string(s, "quota-type", quota_type, &quota_type);
834
835 if (uid_str.empty()) {
836 http_ret = -EINVAL;
837 return;
838 }
839
840 rgw_user uid(uid_str);
841
842 bool set_all = quota_type.empty();
843 bool set_bucket = set_all || (quota_type == "bucket");
844 bool set_user = set_all || (quota_type == "user");
845
846 if (!(set_all || set_bucket || set_user)) {
847 ldout(store->ctx(), 20) << "invalid quota type" << dendl;
848 http_ret = -EINVAL;
849 return;
850 }
851
852 bool use_http_params;
853
854 if (s->content_length > 0) {
855 use_http_params = false;
856 } else {
857 const char *encoding = s->info.env->get("HTTP_TRANSFER_ENCODING");
858 use_http_params = (!encoding || strcmp(encoding, "chunked") != 0);
859 }
860
861 if (use_http_params && set_all) {
862 ldout(store->ctx(), 20) << "quota type was not specified, can't set all quotas via http headers" << dendl;
863 http_ret = -EINVAL;
864 return;
865 }
866
867 op_state.set_user_id(uid);
868
869 RGWUser user;
870 http_ret = user.init(store, op_state);
871 if (http_ret < 0) {
872 ldout(store->ctx(), 20) << "failed initializing user info: " << http_ret << dendl;
873 return;
874 }
875
876 if (!op_state.has_existing_user()) {
877 http_ret = -ERR_NO_SUCH_USER;
878 return;
879 }
880
881 #define QUOTA_INPUT_MAX_LEN 1024
882 if (set_all) {
883 UserQuotas quotas;
884
885 if ((http_ret = rgw_rest_get_json_input(store->ctx(), s, quotas, QUOTA_INPUT_MAX_LEN, NULL)) < 0) {
886 ldout(store->ctx(), 20) << "failed to retrieve input" << dendl;
887 return;
888 }
889
890 op_state.set_user_quota(quotas.user_quota);
891 op_state.set_bucket_quota(quotas.bucket_quota);
892 } else {
893 RGWQuotaInfo quota;
894
895 if (!use_http_params) {
896 bool empty;
897 http_ret = rgw_rest_get_json_input(store->ctx(), s, quota, QUOTA_INPUT_MAX_LEN, &empty);
898 if (http_ret < 0) {
899 ldout(store->ctx(), 20) << "failed to retrieve input" << dendl;
900 if (!empty)
901 return;
902
903 /* was probably chunked input, but no content provided, configure via http params */
904 use_http_params = true;
905 }
906 }
907
908 if (use_http_params) {
909 RGWUserInfo info;
910 string err_msg;
911 http_ret = user.info(info, &err_msg);
912 if (http_ret < 0) {
913 ldout(store->ctx(), 20) << "failed to get user info: " << http_ret << dendl;
914 return;
915 }
916 RGWQuotaInfo *old_quota;
917 if (set_user) {
918 old_quota = &info.user_quota;
919 } else {
920 old_quota = &info.bucket_quota;
921 }
922
923 RESTArgs::get_int64(s, "max-objects", old_quota->max_objects, &quota.max_objects);
924 RESTArgs::get_int64(s, "max-size", old_quota->max_size, &quota.max_size);
925 int64_t max_size_kb;
926 bool has_max_size_kb = false;
927 RESTArgs::get_int64(s, "max-size-kb", 0, &max_size_kb, &has_max_size_kb);
928 if (has_max_size_kb) {
929 quota.max_size = max_size_kb * 1024;
930 }
931 RESTArgs::get_bool(s, "enabled", old_quota->enabled, &quota.enabled);
932 }
933
934 if (set_user) {
935 op_state.set_user_quota(quota);
936 } else {
937 op_state.set_bucket_quota(quota);
938 }
939 }
940
941 string err;
942 http_ret = user.modify(op_state, &err);
943 if (http_ret < 0) {
944 ldout(store->ctx(), 20) << "failed updating user info: " << http_ret << ": " << err << dendl;
945 return;
946 }
947 }
948
949 RGWOp *RGWHandler_User::op_get()
950 {
951 if (s->info.args.sub_resource_exists("quota"))
952 return new RGWOp_Quota_Info;
953
954 if (s->info.args.sub_resource_exists("list"))
955 return new RGWOp_User_List;
956
957 return new RGWOp_User_Info;
958 }
959
960 RGWOp *RGWHandler_User::op_put()
961 {
962 if (s->info.args.sub_resource_exists("subuser"))
963 return new RGWOp_Subuser_Create;
964
965 if (s->info.args.sub_resource_exists("key"))
966 return new RGWOp_Key_Create;
967
968 if (s->info.args.sub_resource_exists("caps"))
969 return new RGWOp_Caps_Add;
970
971 if (s->info.args.sub_resource_exists("quota"))
972 return new RGWOp_Quota_Set;
973
974 return new RGWOp_User_Create;
975 }
976
977 RGWOp *RGWHandler_User::op_post()
978 {
979 if (s->info.args.sub_resource_exists("subuser"))
980 return new RGWOp_Subuser_Modify;
981
982 return new RGWOp_User_Modify;
983 }
984
985 RGWOp *RGWHandler_User::op_delete()
986 {
987 if (s->info.args.sub_resource_exists("subuser"))
988 return new RGWOp_Subuser_Remove;
989
990 if (s->info.args.sub_resource_exists("key"))
991 return new RGWOp_Key_Remove;
992
993 if (s->info.args.sub_resource_exists("caps"))
994 return new RGWOp_Caps_Remove;
995
996 return new RGWOp_User_Remove;
997 }
998