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