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